docs: define protocol data model
This commit is contained in:
+4
-4
@@ -38,7 +38,7 @@ WIPではObjectを受動的なJSON recordとして扱わない。
|
|||||||
|
|
||||||
Operationには、名前や型に加えて、用途を判断するための短いdescriptionを持たせる。長文documentationや大量のドメインデータをInterfaceへ埋め込むことは想定しない。
|
Operationには、名前や型に加えて、用途を判断するための短いdescriptionを持たせる。長文documentationや大量のドメインデータをInterfaceへ埋め込むことは想定しない。
|
||||||
|
|
||||||
ObjectはOperation定義を直接埋め込まず、WIP IDLで記述されたInterfaceを参照する。一つのInterfaceに宣言された関数の集合がOperation一覧となり、複数のObjectが同じInterfaceを共有できる。
|
ObjectはOperation定義を直接埋め込まず、実装コード上のInterface Declarationから生成されたInterface Descriptorを参照する。一つのInterfaceに宣言された関数の集合がOperation一覧となり、複数のObjectが同じInterfaceを共有できる。
|
||||||
|
|
||||||
## 発見と既知世界
|
## 発見と既知世界
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ Clientは、これまでに発見したエントリを既知のWorldspaceとし
|
|||||||
|
|
||||||
OperationはHost背後の環境を変更し得るが、WIPはその状態遷移や変更差分をClientへ同期するprotocolではない。
|
OperationはHost背後の環境を変更し得るが、WIPはその状態遷移や変更差分をClientへ同期するprotocolではない。
|
||||||
|
|
||||||
Operation Resultは型付きの値であり、WIP IDLの`entry`型として、未観測だったエントリのpathを返せる。例えばRAG検索からResult群を発見したり、Agentへの問い合わせからConversationを発見したりできる。
|
Operation Resultは型付きの値であり、Interface Descriptorの`entry`型として、未観測だったエントリのpathを返せる。例えばRAG検索からResult群を発見したり、Agentへの問い合わせからConversationを発見したりできる。
|
||||||
|
|
||||||
Clientは必要に応じて返されたpathを取得し、変更後の状態を改めて観測する。
|
Clientは必要に応じて返されたpathを取得し、変更後の状態を改めて観測する。
|
||||||
|
|
||||||
@@ -58,11 +58,11 @@ Clientは必要に応じて返されたpathを取得し、変更後の状態を
|
|||||||
|
|
||||||
WIPの目的は、Filesystem、GitHub、RAG、DBなどを一つの巨大APIへ統合することではない。
|
WIPの目的は、Filesystem、GitHub、RAG、DBなどを一つの巨大APIへ統合することではない。
|
||||||
|
|
||||||
任意のデジタル環境を共通のWorldspaceとして投影し、発見・観測・Operation実行という小さなInteraction Modelへ収束させる。Host内部のAPI、DB、RPC、永続化方式は規定せず、TransportもCore Protocolから分離する。
|
任意のデジタル環境を共通の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 Protocolの規定対象外とする。
|
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が実行時に評価する。
|
Clientが保持するKnown SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheであり、Host上の現在状態を同期したreplicaではない。HostがClientのcache状態を追跡または更新することを要求しない。Operationのauthorizationと実行条件はHostが実行時に評価する。
|
||||||
|
|
||||||
|
|||||||
+77
-16
@@ -1,32 +1,73 @@
|
|||||||
# 2. コアモデル
|
# 2. コアモデル
|
||||||
|
|
||||||
|
WIP Core Modelは、ClientがHostの提供するWorldspaceを観測し、Objectを発見し、Interfaceに従って操作するための意味論を定義する。
|
||||||
|
|
||||||
|
具体的なrequest / response structは[3. Protocol](3-protocol.md)、HTTPとJSONへの対応付けは[WIP over HTTPS](draft/wip-over-https.md)で定義する。
|
||||||
|
|
||||||
## 基本構造
|
## 基本構造
|
||||||
|
|
||||||
Worldspaceは、LLMが探索できる**ObjectのTree**として公開される。
|
Worldspaceは、Clientが探索できる**ObjectのTree**として公開される。
|
||||||
|
|
||||||
WIPではObjectとエントリを別の構造として定義しない。**ObjectをWorldspaceのTree上の位置として扱うとき、そのObjectをエントリと呼ぶ。**
|
WIPではObjectとエントリを別の構造として定義しない。**ObjectをWorldspaceのTree上の位置として扱うとき、そのObjectをエントリと呼ぶ。**
|
||||||
|
|
||||||
したがって、ObjectはTree上で親子関係を持ち得るし、途中のNodeもそのまま操作対象になってよい。例えば`articles`はCollection Objectとして、そのInterfaceに`query`等を宣言し、配下に個別Articleを配置できる。
|
したがって、ObjectはTree上で親子関係を持ち得るし、途中のNodeもそのまま操作対象になってよい。例えば`articles`はCollection Objectとして、そのInterfaceに`query`等を宣言し、配下に個別Articleを配置できる。
|
||||||
|
|
||||||
|
## ClientとHost
|
||||||
|
|
||||||
|
WIP上の主要な実装主体は**Client**と**Host**である。
|
||||||
|
|
||||||
|
### Client
|
||||||
|
|
||||||
|
Clientは、Hostが提供するWorldspaceをユーザーまたはAIへ提示する。
|
||||||
|
|
||||||
|
Hostから取得したObjectとInterface Descriptorをcacheし、`ref`によるObject同一性の追跡、観測時と操作時の対応関係の検証、GUI、AI用Tools、PTC / REPL向けAPI等への投影を行う。
|
||||||
|
|
||||||
|
### Host
|
||||||
|
|
||||||
|
Hostは、Clientに対して一つのWorldspaceを提供する。
|
||||||
|
|
||||||
|
どのObject、エントリ、Interface、可視性を公開するかを決定し、そのClientから見えるWorldspaceを構成する。
|
||||||
|
|
||||||
|
Host内部でGitHub API、Database、Filesystem、RAG、他Agent、別protocol等をどう接続、集約、永続化するかはWIPの規定対象外とする。
|
||||||
|
|
||||||
|
ClientとHostの境界は通信境界であると同時に、ある主体へどのWorldspaceを公開するかを決めるtrust boundaryである。
|
||||||
|
|
||||||
## Object / エントリ
|
## Object / エントリ
|
||||||
|
|
||||||
**Object**はWIP上で観測・操作される対象そのものである。
|
**Object**は、Worldspace上で観測および操作できる対象のprotocol-level projectionである。
|
||||||
|
|
||||||
|
Objectは、探索に必要な公開情報とInterface参照を持つ。Host内部のdomain entityやApplication dataをそのままObjectとして公開する必要はない。Objectの本文、状態、domain metadata等は、Interfaceに宣言されたOperationを通して取得または変更する。
|
||||||
|
|
||||||
**エントリ**は、そのObjectをTree上の位置として見たときの呼び名である。
|
**エントリ**は、そのObjectをTree上の位置として見たときの呼び名である。
|
||||||
|
|
||||||
エントリがObjectへの参照を別途持つ、という二重構造は前提としない。
|
エントリがObjectへの参照を別途持つ、という二重構造は前提としない。
|
||||||
|
|
||||||
Tree上の位置はpathで表される。Pathは恒久的なIdentityではなく、その時点でのnavigation coordinateである。
|
Tree上の位置はpathで表される。Pathはrootから各Objectの`name`を順に`/`で連結して構成する。Pathは恒久的なIdentityではなく、その時点でのnavigation coordinateである。
|
||||||
|
|
||||||
同じObjectが複数の位置に現れる場合、一つのObjectが複数のエントリとして観測され得る。
|
同じ親の直下ではObjectの`name`は一意であり、非root Objectの`name`は空であってはならない。同じObjectが複数の位置に現れる場合、一つのObjectが異なる`name`とpathを持つ複数のエントリとして観測され得る。Objectの公開情報、name、path、Tree上の配置については[2.1. Object tree / Schema](2.1-object-tree-schema.md)で扱う。
|
||||||
|
|
||||||
## Interface
|
## Interface
|
||||||
|
|
||||||
ObjectはOperation定義を直接持たず、一つのInterfaceを参照する。
|
ObjectはOperation定義を直接持たず、一つのInterfaceを参照する。
|
||||||
|
|
||||||
Interfaceの実体は一つのWIP IDL documentであり、document内に宣言された関数の集合が、そのInterfaceのOperation集合となる。複数のObjectが同じInterfaceを共有できる。
|
Interfaceは、Objectで利用できるOperation、parameter、return type、documentationを定義する。Interface実装者はRustのtraitやTypeScriptのdefinition API等を使って実装コード上でInterfaceを宣言し、Libraryはその宣言からmachine-readableなInterface Descriptorを生成する。
|
||||||
|
|
||||||
ObjectとInterfaceを分離することで、Collection内の多数の同種Objectに同じOperation定義を重複して持たせず、ClientがInterface定義を参照単位でcacheできる。
|
複数のObjectが同じInterfaceを共有できる。ObjectとInterfaceを分離することで、Collection内の多数の同種Objectに同じOperation定義を重複して持たせず、ClientがInterface Descriptorを参照単位でcacheできる。
|
||||||
|
|
||||||
|
InterfaceとOperationの意味論は[2.2. Interface / Operation](2.2-operation.md)、Descriptorのlogical structは[3. Protocol](3-protocol.md)、人間とAIへの表示は[4.1. AI用Tools](4.1-ai-tools-example.md)で扱う。
|
||||||
|
|
||||||
|
## Core interaction
|
||||||
|
|
||||||
|
Clientは、次の4操作によってWorldspaceを観測および操作する。
|
||||||
|
|
||||||
|
- `fetch(path)` — 一つのpathで現在公開されているObjectを取得する。
|
||||||
|
- `fetch_tree(path, depth, limit)` — 指定pathを起点にindexableな子ObjectをTreeとして取得する。
|
||||||
|
- `fetch_interface(interface)` — Interface参照からInterface Descriptorを取得する。
|
||||||
|
- `call_operation(target, operation, arguments)` — `path`とoptionalな`validator`を持つtargetに対してOperationを実行する。
|
||||||
|
|
||||||
|
この節は各操作の意味だけを定める。Parameterとreturn valueの具体的なstructはProtocolで定義する。
|
||||||
|
|
||||||
|
複数の`fetch`や`fetch_interface`は、それぞれ独立したCore interactionである。Transport Bindingは、個別に実行した場合と同じ意味を保ったまま複数のinteractionを一つのrequestへbatchしてよい。Batchingによって新しいCore interactionや暗黙の先読みを導入しない。
|
||||||
|
|
||||||
## `ref`
|
## `ref`
|
||||||
|
|
||||||
@@ -39,6 +80,7 @@ Objectは必要に応じて`ref`を公開できる。
|
|||||||
- `ref`のscopeや有効期間はWorldspaceまたは実装が定めてよい。
|
- `ref`のscopeや有効期間はWorldspaceまたは実装が定めてよい。
|
||||||
- `ref`はグローバルかつ永続的なUIDである必要はない。
|
- `ref`はグローバルかつ永続的なUIDである必要はない。
|
||||||
- 同じObjectが複数のエントリとして観測される場合、同じ`ref`によって同一性を示せる。
|
- 同じObjectが複数のエントリとして観測される場合、同じ`ref`によって同一性を示せる。
|
||||||
|
- `ref`はnavigation coordinateではない。Objectの取得にはentry pathを使用する。
|
||||||
|
|
||||||
## 観測整合性
|
## 観測整合性
|
||||||
|
|
||||||
@@ -48,24 +90,43 @@ Objectは必要に応じて`ref`を公開できる。
|
|||||||
|
|
||||||
例えば、AIが`/issues/current`を観測した時点ではIssue Aだったが、`invoke`時にはIssue Bへ差し替わっていた場合、AIはIssue Aへ作用するつもりでIssue Bを操作してしまう可能性がある。
|
例えば、AIが`/issues/current`を観測した時点ではIssue Aだったが、`invoke`時にはIssue Bへ差し替わっていた場合、AIはIssue Aへ作用するつもりでIssue Bを操作してしまう可能性がある。
|
||||||
|
|
||||||
この観測整合性は利用者に追跡させるのではなく、クライアントの責務とする。
|
この観測整合性は利用者に追跡させるのではなく、Clientの責務とする。
|
||||||
|
|
||||||
処理の流れは次の通り。
|
処理の流れは次の通り。
|
||||||
|
|
||||||
1. Clientがpath上のObjectを観測する。
|
1. Clientがpath上のObjectを観測する。
|
||||||
2. Clientはその時点のpathとObjectの対応を内部的に記録する。
|
2. Objectがvalidatorを持つ場合、ClientはObjectとrequest pathを対応付けて保持する。
|
||||||
3. モデルは観測したObjectについて推論する。
|
3. ユーザーまたはAIが観測したObjectについて判断する。
|
||||||
4. モデルが同じpathを対象に操作を要求した場合、Client / Runtimeは実行前に対応関係が変化していないことを検証する。
|
4. 同じObjectへ条件付きで操作する場合、Clientは`path`とObjectの`validator`をtargetとしてHostへ渡す。
|
||||||
|
5. Hostは現在のvalidatorとの一致確認とOperation実行をatomicに行う。
|
||||||
|
|
||||||
実装はETagやgeneration、opaque token等の内部メタデータを用いてよいが、それらを利用者へ露出する必要はない。
|
ValidatorはClientとHostの間で扱い、AIやユーザーに直接管理させない。Transport Bindingは、同じlogical semanticsを保つ形でHTTP ETag等へ対応付けてよい。
|
||||||
|
|
||||||
対応関係が変化していた場合、Clientは新しいObjectに対して操作を自動的に再試行してはならない。操作を中止し、`target_changed`のような意味的エラーを返して再観測を要求する。
|
Validatorが一致しない場合、Clientは現在のObjectに対してOperationを自動的に再試行してはならない。Hostは`validator_mismatch`を返し、Clientは再観測を要求する。
|
||||||
|
|
||||||
## 同一性と観測整合性の分離
|
## 同一性と観測整合性の分離
|
||||||
|
|
||||||
WIPでは次の2つを分けて扱う。
|
WIPでは次の二つを分けて扱う。
|
||||||
|
|
||||||
- **Object identity (`ref`)**: 複数の観測にまたがって同一Objectであることを明示するための任意の外部Handle。
|
- **Object identity (`ref`)** — 複数の観測にまたがって同一Objectであることを明示するための任意の外部Handle。
|
||||||
- **Observation consistency**: `ref`の有無に関わらず、観測したpath上のObjectと操作対象のObjectが一致していることをClient / Runtimeが保証する仕組み。
|
- **Observation consistency** — `ref`の有無にかかわらず、観測したpath上のObjectと操作対象のObjectが一致していることを保証する仕組み。
|
||||||
|
|
||||||
したがって、`ref`を持たないObjectであっても安全な操作対象になり得る。`ref`は同一性を公開する仕組みであり、Observation consistencyは操作の安全性を担保する仕組みである。
|
したがって、`ref`を持たないObjectであっても安全な操作対象になり得る。`ref`は同一性を公開する仕組みであり、validatorはHostが定める現在状態との一致を条件付きOperationで検証する仕組みである。
|
||||||
|
|
||||||
|
## 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の責務である。
|
||||||
|
|
||||||
|
Clientが保持するKnown SpaceとDiscoverable Spaceは、過去の観測から構成されたcacheであり、Host上の現在状態を同期したreplicaではない。HostがClientのcache状態を追跡または更新することを要求しない。
|
||||||
|
|
||||||
|
この責務境界はObject、Interface、Operationの各節で一貫して適用する。
|
||||||
|
|
||||||
|
## Transportとの分離
|
||||||
|
|
||||||
|
Core ModelとProtocol structは、HTTP、TCP、WebSocket等の特定transportを要求しない。
|
||||||
|
|
||||||
|
通信方式、concrete encoding、endpoint、batch packagingへの対応付けはTransport Bindingとして定義する。標準bindingは[WIP over HTTPS](draft/wip-over-https.md)で扱う。
|
||||||
|
|
||||||
|
この分離により、Worldspaceの意味論、Client / Host間のlogical contract、通信方式を独立して進化させる。
|
||||||
|
|||||||
+137
-39
@@ -1,75 +1,173 @@
|
|||||||
# 2.1. Object tree / Schema
|
# 2.1. Object tree / Schema
|
||||||
|
|
||||||
## 2.1.1 目的
|
## Objectの公開情報
|
||||||
|
|
||||||
このページでは、WIP Core ModelにおけるObject treeと、それらをClientへ公開する際の最小スキーマを整理する。
|
Objectは、Worldspace上の対象を発見し、理解し、操作するためのprotocol-level projectionである。
|
||||||
|
|
||||||
WIPでは、**Objectとエントリを別のデータ構造として定義しない**。ObjectをWorldspaceのTree上に配置されたものとして扱うとき、そのObjectをエントリと呼ぶ。
|
Objectは少なくとも次の公開情報を持つ。
|
||||||
|
|
||||||
## 2.1.2 Objectとエントリ
|
- **name** — 親Objectの下でのpath segment。
|
||||||
|
- **description** — Objectが何を表すかを説明する情報。
|
||||||
|
- **interface** — Objectで利用できるOperationを定義するInterfaceへの参照。
|
||||||
|
- **ref** — 同じObjectを複数の観測にまたがって識別するための任意の外部Handle。
|
||||||
|
- **validator** — HostがObjectの現在状態へ付与する任意のopaque value。
|
||||||
|
|
||||||
**Object**はWIP上で観測・操作される対象そのものである。
|
具体的な型、必須性、resource limitは[3. Protocol](3-protocol.md)で定義する。
|
||||||
|
|
||||||
**エントリ**は、そのObjectをWorldspaceのTree上の位置として見たときの呼び名である。
|
Objectの本文、状態、domain metadata等のApplication dataを、共通のproperty bagとしてObjectへ格納しない。それらはInterfaceに宣言されたOperationを通して取得または変更する。
|
||||||
|
|
||||||
したがって、エントリがObjectへの参照を別途保持する、あるいはエントリ schemaとObject schemaを二重に定義することは前提としない。
|
`description`は探索時に対象を理解するための短い公開情報であり、長い本文やdomain entityの完全な表現を格納する場所ではない。
|
||||||
|
|
||||||
ObjectがTree上に配置されることでエントリとなり、pathはその配置位置を表すnavigation coordinateとなる。
|
## Interface参照
|
||||||
|
|
||||||
同じObjectが複数の位置に現れる場合、一つのObjectが複数のエントリとして観測され得る。
|
Objectは一つのInterfaceを参照する。
|
||||||
|
|
||||||
## 2.1.3 公開情報
|
Interfaceは次を定義する。
|
||||||
|
|
||||||
Object / エントリが公開する情報は、Worldspaceを探索し、対象に対して何ができるかを理解するための最小限のmetadataである。
|
- Operation名
|
||||||
|
- Operationの説明
|
||||||
|
- Parameter名と型
|
||||||
|
- Return type
|
||||||
|
- Named typeとdocumentation
|
||||||
|
|
||||||
現時点では、少なくとも次の情報を想定する。
|
Interface実装者は実装コード上でInterfaceを宣言し、Libraryはその宣言からInterface Descriptorを生成する。ClientはObjectのInterface参照を使ってDescriptorを取得し、検証、cache、表示、Operation callのvalidationに利用する。
|
||||||
|
|
||||||
- `name` — Objectの短い名前。Tree上ではエントリ名としても用いられる。
|
同じInterfaceを持つObjectは同じDescriptor参照を共有できる。
|
||||||
- `description` — Objectが何を表すかを説明する短い自然言語。長文documentationではなく、探索・判断に必要な最小限のsemantic metadataとする。
|
|
||||||
- `interface` — Objectが実装するInterfaceへの参照。
|
|
||||||
- `children` — Tree上でindexableとして公開される子Object / エントリ。
|
|
||||||
- `ref` — 必要に応じて公開される、同一Objectを再参照するための外部Handle。
|
|
||||||
|
|
||||||
Interfaceの実体は[WIP IDL](draft/wip-idl.md) documentである。IDL内に宣言された関数の集合が、そのInterfaceのOperation集合となる。ObjectはOperation定義を個別に埋め込まず、一つのInterface参照だけを持つ。
|
## Object / エントリ / path
|
||||||
|
|
||||||
複数のObjectが同じInterfaceを参照できる。これにより、Collectionから多数の同種エントリを取得する場合でも、Operation名、documentation、parameter、return typeを各エントリへ重複して送る必要がない。
|
WIPでは、Objectとエントリを別のdomain entityとして定義しない。ObjectをTree上の位置として扱うとき、そのObjectをエントリと呼ぶ。
|
||||||
|
|
||||||
Interface参照は、HostがそのClientへ投影したInterfaceを識別する。同じObjectでも主体のroleや権限により異なるInterfaceを参照し得るが、頻繁に変化する実行可否を表すためには使用しない。
|
### `name`
|
||||||
|
|
||||||
ClientはInterface参照をcacheと比較し、未知のInterfaceだけを`fetch_interface`で取得する。HostはClientのcache状態を推測せず、ObjectのresponseへInterface定義を先行同梱しない。複数のInterface取得はTransport Bindingでbatchできる。
|
Objectの`name`は表示用labelではなく、親Objectの下でそのObjectを識別するpath segmentである。
|
||||||
|
|
||||||
WIPではドメインデータそのものをpropertiesとして直接公開することを前提としない。本文、metadata、状態などを読む行為もOperationとして表現する。
|
- Root Objectの`name`は空文字列とする。
|
||||||
|
- 非root Objectの`name`は空であってはならない。
|
||||||
|
- `name`に`/`を含めてはならない。
|
||||||
|
- `name`全体が`.`または`..`であってはならない。
|
||||||
|
- `name`はUnicode stringとする。
|
||||||
|
- Unicode normalizationは行わない。
|
||||||
|
- Nameの比較はUnicode code point sequenceの完全一致で行う。
|
||||||
|
- 同じ親の直接のchildrenは、互いに異なる`name`を持たなければならない。
|
||||||
|
|
||||||
## 2.1.4 Tree
|
`name`を人間向けの自由なtitleとして扱わない。探索時の短い説明には`description`を使い、domain上のtitle等はOperationからApplication dataとして取得する。
|
||||||
|
|
||||||
Worldspaceは、Objectが親子関係によって配置されたTreeとして観測される。
|
### Pathの構成
|
||||||
|
|
||||||
Tree上のObjectをエントリとして呼び、その位置をpathで表す。
|
Rootのpathは`/`とする。非root Objectのpathは、rootからそのObjectまでの各`name`を`/`で連結して構成する。
|
||||||
|
|
||||||
子エントリは所有・内包関係を表す。非内包の意味的関係は、それを表すOperationから関連エントリのpathを返す。
|
```text
|
||||||
|
root.name = ""
|
||||||
|
root.path = "/"
|
||||||
|
|
||||||
例えばRepository配下の`issues`は子エントリとして自然だが、Issueから関連Pull Requestを得る場合は`get_related_pull_requests`のようなOperationで表現する。
|
projects.name = "projects"
|
||||||
|
projects.path = "/projects"
|
||||||
|
|
||||||
Treeはmaterializedな全世界ではなく、HostがそのClientに対して公開する**lazy / virtual tree**である。Hostは全Objectを事前保持する必要はなく、`fetch`や`fetch_tree`に応じて動的に解決してよい。
|
example.name = "example"
|
||||||
|
example.path = "/projects/example"
|
||||||
|
```
|
||||||
|
|
||||||
## 2.1.5 Indexable children
|
Pathには空segment、`.`、`..`を含めない。Root以外のpathは末尾に`/`を持たない。Nameに`/`を許可しないため、Core Modelではsegment escapeを定義しない。Transport BindingがPathをURL componentへ格納する場合のURL encodingは、WIP Pathの構成とは別に扱う。
|
||||||
|
|
||||||
子エントリには、機械的探索で辿ってよいものと、Operationによってのみ発見されるものがある。
|
非root pathについては、最後のsegmentと取得したObjectの`name`が一致しなければならない。
|
||||||
|
|
||||||
`fetch_tree`が辿るのは**indexableとして公開された子エントリのみ**とする。
|
```text
|
||||||
|
fetch("/projects/example")
|
||||||
|
-> Object.name == "example"
|
||||||
|
```
|
||||||
|
|
||||||
indexableな子エントリは、Worldspaceの構造理解に必要で、通常は件数が小さいものを想定する。
|
同じObjectが複数のpathへ配置される場合、同じ`ref`を持ちながら配置ごとに異なる`name`を持ち得る。Objectをrenameまたは別の親へ移動すると、そのObjectとdescendantのpathは変化する。Pathは恒久的なObject identityとして使用しない。
|
||||||
|
|
||||||
一方、大量のIssue、検索結果、一時的なObject群などはindexable childとして露出しない。必要なエントリはCollection Objectの`query` / `list`等のOperation結果として返す。
|
`ref`、path、Interface参照は異なる役割を持つ。
|
||||||
|
|
||||||
Operation結果として返されることは、実行対象との親子関係を意味しない。Collectionの要素を返す場合だけでなく、親、兄弟、関連Objectなど、Worldspace内の別の位置にあるエントリを発見するためにもOperationを利用できる。
|
| 値 | 役割 |
|
||||||
|
| --- | --- |
|
||||||
|
| path / `entry` | RootからObjectの`name`を辿って構成するnavigation coordinate |
|
||||||
|
| `ref` | 複数の観測にまたがる任意のObject identity |
|
||||||
|
| Interface参照 | Objectで利用可能なcapability definition |
|
||||||
|
|
||||||
## 2.1.6 Core Protocolとの対応
|
通常のstringを内容だけからpathまたは`ref`と推測しない。Operation value内でWorldspace上の位置を返す場合は、Descriptorで`entry`型として宣言する。
|
||||||
|
|
||||||
`fetch(entry)`は、指定されたTree上の位置にあるObjectの公開情報を取得する。
|
## Tree
|
||||||
|
|
||||||
`fetch_tree(entry, depth, limit)`は、指定エントリからindexable child edgeだけを幅優先探索し、Treeとしてまとめて返す。
|
Objectは子Objectを持つことができる。
|
||||||
|
|
||||||
探索が`depth`または`limit`により打ち切られた場合は、レスポンスで`truncated`を必ず明示する。
|
Parent / child関係はWorldspaceにおける**所有または内包**を表す。
|
||||||
|
|
||||||
Operationを実行した結果には、WIP IDLの`entry`型として新しいエントリのpathが含まれる場合がある。Clientはそれらを一時的な発見結果として扱い、後続の参照に必要なものだけを取得してKnown Spaceへ統合できる。
|
- Filesystem: Directory / File
|
||||||
|
- GitHub: Repository / Issue
|
||||||
|
- Database: Database / Table
|
||||||
|
- RAG: Index / Document
|
||||||
|
|
||||||
|
関連、依存、参照等の非所有関係を、Treeの親子関係として濫用しない。そのような関係はOperationのresultとして`entry`を返し、Clientが必要に応じて移動できるようにする。
|
||||||
|
|
||||||
|
### `children`の意味
|
||||||
|
|
||||||
|
`children`はApplication dataではなく、Objectを指定pathで観測した時点におけるWorldspace上のprojectionである。
|
||||||
|
|
||||||
|
一つのObjectが複数pathへ配置される場合、そのObjectから見えるchildrenは配置ごとに異なり得る。したがって、childrenを`ref`が示すObject identityの一部とはみなさない。
|
||||||
|
|
||||||
|
Protocolでは`Object`自体にchildrenとpathを含めず、`fetch_tree`の`ObjectTreeNode`としてObjectとchildrenをまとめる。ValidatorはObjectに含まれる。各nodeのpathは、request pathを起点にObjectの`name`を辿って導出する。このwrapperはObjectとは別のdomain entityを導入するものではなく、Tree traversalのresponse shapeである。
|
||||||
|
|
||||||
|
## `fetch`
|
||||||
|
|
||||||
|
`fetch(path)`は、指定されたpathで現在公開されている一つのObjectを観測する。
|
||||||
|
|
||||||
|
```text
|
||||||
|
fetch(path) -> Object
|
||||||
|
```
|
||||||
|
|
||||||
|
返されたObjectは、Host内部のdomain entityの完全なcopyではない。そのClientへ現在公開されているname、description、Interface参照、任意の`ref`とvalidator等のprotocol projectionである。Clientは非rootのrequest pathについて、最後のsegmentとObjectの`name`が一致することを検証する。
|
||||||
|
|
||||||
|
ClientはObjectがvalidatorを持つ場合、そのObjectとrequest pathを対応付けて保持し、条件付きOperationのtargetを構築できる。
|
||||||
|
|
||||||
|
## `fetch_tree`
|
||||||
|
|
||||||
|
`fetch_tree(path, depth, limit)`は、指定pathを起点にindexableな子ObjectをTreeとして取得する。
|
||||||
|
|
||||||
|
```text
|
||||||
|
fetch_tree(path, depth, limit) -> ObjectTree
|
||||||
|
```
|
||||||
|
|
||||||
|
探索順序は**Breadth-First Search (BFS)**とする。
|
||||||
|
|
||||||
|
- `depth`は起点Objectを`0`とする最大深さ。
|
||||||
|
- `limit`はresponse全体に含めるObject数の上限。
|
||||||
|
- 起点Objectはlimitへ含める。
|
||||||
|
- `depth`または`limit`によって存在するindexable childを省略した場合は、responseで`truncated = true`を返す。
|
||||||
|
- 要求範囲内のindexable childをすべて含む場合は、`truncated = false`を返す。
|
||||||
|
|
||||||
|
Tree responseは各nodeにObjectを含み、Clientはrequest pathとchildrenの`name`から各Objectのpathを導出する。各ObjectはHostが発行したvalidatorを持ち得るため、Clientは導出したpathとvalidatorから条件付きOperationのtargetを構築できる。
|
||||||
|
|
||||||
|
Depth、limitの有効範囲、Tree node、truncationの具体的なstructはProtocolで定義する。
|
||||||
|
|
||||||
|
## Indexable children
|
||||||
|
|
||||||
|
Tree上のchildrenとして自然に列挙できるのは、**indexableなObject**だけである。
|
||||||
|
|
||||||
|
- 件数がboundedまたは現実的な範囲で列挙できる。
|
||||||
|
- 比較的安価に取得できる。
|
||||||
|
- 所有または内包関係として自然に理解できる。
|
||||||
|
|
||||||
|
全件列挙が高コストまたは不自然な集合は、Treeへ直接展開しない。Collection ObjectのOperationを使って検索、filter、paginationを行い、resultとして関連する`entry`を返す。
|
||||||
|
|
||||||
|
例えば、大規模なIssue collectionは次のように公開できる。
|
||||||
|
|
||||||
|
```text
|
||||||
|
/issues
|
||||||
|
interface: IssueCollection
|
||||||
|
operation: query(filter, cursor, limit) -> IssueQueryResult
|
||||||
|
```
|
||||||
|
|
||||||
|
```text
|
||||||
|
IssueQueryResult.items: [entry]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Batch
|
||||||
|
|
||||||
|
複数のObjectやInterface Descriptorをまとめて取得する機能は、Core Model上の新しいinteractionではない。
|
||||||
|
|
||||||
|
Transport Bindingは、個別に実行した場合と同じ意味を保つ形で、複数の`fetch`、`fetch_tree`、`fetch_interface`を一つのrequestへまとめてよい。
|
||||||
|
|
||||||
|
WIPは自動的な全量取得、暗黙の再帰展開、Clientが要求していない先読みを要求しない。
|
||||||
|
|||||||
+120
-24
@@ -1,24 +1,35 @@
|
|||||||
# 2.2. Operation
|
# 2.2. Interface / Operation
|
||||||
|
|
||||||
## 2.2.1 目的
|
## Interface
|
||||||
|
|
||||||
Operationは、Objectに対して実行できる操作を表す。
|
|
||||||
|
|
||||||
WIPでは、本文を読む、metadataを取得する、検索する、状態を変更するなど、Objectに対する行為をOperationとして公開する。
|
|
||||||
|
|
||||||
## 2.2.2 Interface
|
|
||||||
|
|
||||||
ObjectはOperation定義を直接持たず、一つのInterfaceを参照する。
|
ObjectはOperation定義を直接持たず、一つのInterfaceを参照する。
|
||||||
|
|
||||||
Interfaceの定義は[WIP IDL](draft/wip-idl.md) documentそのものである。IDL documentに宣言された関数の集合が、そのInterfaceのOperation集合となる。Operation名、parameter、return type、短いdocumentationは一つの関数宣言としてまとめて定義し、別のOperation descriptorへ重複して記述しない。
|
Interfaceは、Objectで利用できるOperationと、各Operationのparameter、return type、documentationを定義する。複数のObjectが同じInterfaceを共有できるため、Operation定義をObjectごとに重複して送る必要はない。
|
||||||
|
|
||||||
複数のObjectが同じInterfaceを参照できる。これにより、Collectionから多数の同種Objectを取得する場合でも、Operation定義を各Objectへ重複して埋め込む必要がない。
|
Interface実装者は、RustのtraitやTypeScriptのdefinition API等を使って実装コード上でInterfaceを宣言する。Libraryはその宣言から、typed handler、runtime validation、およびmachine-readableなInterface Descriptorを生成する。
|
||||||
|
|
||||||
HostはInterfaceについて、参照、IDLのlanguage identifier、source、およびcacheや同一性確認に利用できるdigestをClientへ提供する。ObjectはInterface参照だけを持ち、Clientは未知のInterface定義だけを取得してcacheできる。
|
Interface Descriptorは人間が手書きするschema fileではない。Hostが`fetch_interface`で公開し、Clientが参照単位でcacheするprotocol dataである。
|
||||||
|
|
||||||
## 2.2.3 Operation declaration
|
## Interface Descriptor
|
||||||
|
|
||||||
Operationは、WIP IDL内で関数形式により宣言する。
|
一つのInterface Descriptorは一つのInterfaceを定義し、少なくとも次を保持する。
|
||||||
|
|
||||||
|
- Format version
|
||||||
|
- Interface documentation
|
||||||
|
- Named type declaration
|
||||||
|
- Operation declaration
|
||||||
|
- Operationごとのparameterとreturn type
|
||||||
|
- Type、field、parameter、case等のdocumentation
|
||||||
|
|
||||||
|
Descriptorのlogical structは[3. Protocol](3-protocol.md)で定義する。Code-firstな生成は本章、人間とAIへのSignature Viewは[4.1. AI用Tools](4.1-ai-tools-example.md)で扱う。
|
||||||
|
|
||||||
|
Clientは取得したDescriptorを構造検証および意味検証してからcacheする。Named typeの参照解決、Operation callのvalidation、表示生成には検証済みのInterfaceだけを使用する。
|
||||||
|
|
||||||
|
## Operation declaration
|
||||||
|
|
||||||
|
Operationは、名前付きparameter、return type、documentationを持つ。
|
||||||
|
|
||||||
|
人間とAIへ提示する場合は、Interface DescriptorからIDL風のSignature Viewを生成できる。
|
||||||
|
|
||||||
```wip
|
```wip
|
||||||
/// Returns items related to this Object.
|
/// Returns items related to this Object.
|
||||||
@@ -31,17 +42,31 @@ operation get_related_items(
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameterは常に名前付きとし、位置引数は用いない。引数を持たないOperationは空のparameter list `()`で宣言する。
|
Signature ViewはInterfaceの交換形式や入力言語ではなく、検証済みDescriptorから生成する表示である。
|
||||||
|
|
||||||
|
Parameterは常に名前付きとし、位置引数は用いない。引数を持たないOperationは空のparameter listとして表し、`call_operation`には空のrecordを渡す。
|
||||||
|
|
||||||
```wip
|
```wip
|
||||||
operation refresh() -> unit;
|
operation refresh() -> unit;
|
||||||
```
|
```
|
||||||
|
|
||||||
Return typeには任意のWIP IDL型を使用できる。ただし、将来fieldを追加する可能性があるOperationではrecordを基本とする。
|
Return typeにはDescriptorで定義される任意のvalue typeを使用できる。Evolution compatibilityが必要なOperationでは、fieldを追加できるrecordをreturn typeの基本とする。
|
||||||
|
|
||||||
Operationの用途は`///` documentation commentで簡潔に説明する。長文documentationや大量のdomain dataをInterfaceへ埋め込むことは想定しない。
|
Operationの用途は短いdocumentationで説明する。長文documentationや大量のApplication dataをInterface Descriptorへ埋め込まない。
|
||||||
|
|
||||||
## 2.2.4 可視性
|
## `fetch_interface`
|
||||||
|
|
||||||
|
`fetch_interface(interface)`は、Interface参照に対応するInterface Descriptorを取得する。
|
||||||
|
|
||||||
|
```text
|
||||||
|
fetch_interface(interface) -> Interface Descriptor
|
||||||
|
```
|
||||||
|
|
||||||
|
ObjectはInterface参照だけを持ち、Descriptorを先行同梱しない。ClientはInterface cacheと参照を比較し、未知のDescriptorだけを取得する。
|
||||||
|
|
||||||
|
HostはClientのcache状態を推測して、要求されていないDescriptorをObject responseへ追加しない。複数のDescriptor取得はTransport Bindingでbatchできる。
|
||||||
|
|
||||||
|
## Operationの可視性
|
||||||
|
|
||||||
Hostは、主体の権限やrole / capabilityに基づいて、その主体へ公開するInterfaceを決定してよい。
|
Hostは、主体の権限やrole / capabilityに基づいて、その主体へ公開するInterfaceを決定してよい。
|
||||||
|
|
||||||
@@ -51,16 +76,87 @@ Operationの可視性は、頻繁に変化する実行可否やdomain stateを
|
|||||||
|
|
||||||
WIPはOperationの`available` / `disabled`のような揮発的状態をInterfaceへ同期することを前提としない。現在状態を判断する必要がある場合は、必要に応じてdomain固有のOperationで観測する。最終的なauthorizationと実行条件の判定は`call_operation`時にHostが行う。
|
WIPはOperationの`available` / `disabled`のような揮発的状態をInterfaceへ同期することを前提としない。現在状態を判断する必要がある場合は、必要に応じてdomain固有のOperationで観測する。最終的なauthorizationと実行条件の判定は`call_operation`時にHostが行う。
|
||||||
|
|
||||||
## 2.2.5 Operation Result
|
## `call_operation`
|
||||||
|
|
||||||
`call_operation`は、対象ObjectのInterfaceに宣言されたOperation名と、parameter listに従う名前付きargumentsを受け取る。結果はOperationのreturn typeに従う型付きvalueとして返す。
|
`call_operation`は、指定pathにあるObjectに対して、Interfaceに宣言されたOperationを実行する。
|
||||||
|
|
||||||
Operation Resultには、WIP IDLの`entry`型として新しいエントリのpathが含まれ得る。
|
```text
|
||||||
|
call_operation(target, operation, arguments) -> result, validator?
|
||||||
|
```
|
||||||
|
|
||||||
`entry`は同じWorldspace内のcanonical absolute pathであり、wire上では文字列として表現する。Clientはreturn typeに従って`entry`型の位置を認識し、返されたpathを一時的な発見結果として扱う。通常の`string`や任意JSON値に含まれるpathらしい文字列を、エントリとして推測してはならない。
|
- `target.path`は対象Objectを観測したpath。
|
||||||
|
- `target.validator`はObjectから得たoptionalなopaque validator。
|
||||||
|
- `operation`は対象ObjectのInterfaceに宣言されたOperation名。
|
||||||
|
- `arguments`はOperationのparameterに従う名前付きrecord。
|
||||||
|
- `result`はOperationのreturn typeに従うvalue。
|
||||||
|
- Responseの`validator`はOperation実行後の現在状態に対してHostが発行したoptionalな値。
|
||||||
|
|
||||||
Clientは発見したpathを必要に応じて`fetch`または`fetch_tree`する。複数pathの取得は、それぞれ独立したCore操作をTransport Bindingでbatchする。Operation Resultへエントリ公開情報を先行同梱しない。
|
HostはOperationを実行する前に、次を検証する。
|
||||||
|
|
||||||
Operationの実行対象と、結果として発見されたエントリのTree上の位置は独立している。発見されたエントリは実行対象の子である必要はなく、親、兄弟、またはWorldspace内の任意の位置にあるエントリであってよい。
|
1. `target.path`が存在する。
|
||||||
|
2. `target.validator`が指定されている場合、現在のvalidatorと一致する。
|
||||||
|
3. Objectが参照するInterfaceにOperationが宣言されている。
|
||||||
|
4. Argumentsがparameter declarationに従っている。
|
||||||
|
5. ClientがOperationを実行できる。
|
||||||
|
|
||||||
Operationがエントリpathを返したこと自体から、実行対象との間に親子関係や意味的関係を推論してはならない。親子関係はTree上の配置で表し、非内包の意味的関係はOperation名、resultのfield名、またはdomain固有のrelation型で表現する。
|
Validatorの比較とOperation実行はatomicに行う。一致しない場合、HostはOperationを実行せず`validator_mismatch`を返す。Hostがvalidatorを要求するOperationに指定がない場合は`validator_required`を返す。
|
||||||
|
|
||||||
|
Argumentsに未知のfieldがある場合、必須parameterがない場合、またはvalueが宣言型に一致しない場合、HostはOperationを実行せず`invalid_arguments`を返す。
|
||||||
|
|
||||||
|
ClientはHostから受け取ったresultをreturn typeに従って検証する。Hostが宣言と異なるresultを返した場合は`invalid_result`として扱い、そのvalueをApplicationへ渡さない。
|
||||||
|
|
||||||
|
## Application data
|
||||||
|
|
||||||
|
Operation argumentsとresultは、Applicationが定義し、利用するdataである。
|
||||||
|
|
||||||
|
WIPは次を規定する。
|
||||||
|
|
||||||
|
- Descriptor上の型表現
|
||||||
|
- Transport上のencoding
|
||||||
|
- ClientとHostのboundary validation
|
||||||
|
- `entry`等のWIP固有型の意味
|
||||||
|
|
||||||
|
WIPは次を規定しない。
|
||||||
|
|
||||||
|
- Dataのdomain上の意味
|
||||||
|
- 永続化方法
|
||||||
|
- Application内部のdomain model
|
||||||
|
- Business rule
|
||||||
|
- Clientが取得したdataを利用する方法
|
||||||
|
|
||||||
|
Wire schema上正しいことと、domain上有効であることは別である。例えばargumentsが型に従っていても、現在のdomain stateが操作を許可しない場合、Operation implementationはdomain failureを返し得る。
|
||||||
|
|
||||||
|
## Operation Resultとエントリの発見
|
||||||
|
|
||||||
|
Operation Resultには、Descriptorの`entry`型として新しいエントリのpathが含まれ得る。
|
||||||
|
|
||||||
|
`entry`は同じWorldspace内のcanonical absolute pathである。Clientはreturn typeに従って`entry`型の位置を認識する。通常の`string`やopaqueな`json`に含まれるpathらしい文字列を、エントリとして推測してはならない。
|
||||||
|
|
||||||
|
Clientは発見したpathを必要に応じて`fetch`または`fetch_tree`する。Operation ResultへObject公開情報やInterface Descriptorを先行同梱しない。
|
||||||
|
|
||||||
|
Operationの実行対象と、結果として発見されたエントリのTree上の位置は独立している。発見されたエントリは実行対象の子である必要はなく、親、兄弟、またはWorldspace内の任意の位置にあってよい。
|
||||||
|
|
||||||
|
Operationがpathを返したこと自体から、実行対象との間に親子関係や意味的関係を推論しない。親子関係はTree上の配置で表し、非内包の意味的関係はOperation名、result field名、またはApplication固有のrelation型で表現する。
|
||||||
|
|
||||||
|
## Protocol failureとdomain failure
|
||||||
|
|
||||||
|
Protocol failureは、WIPのrequest、対象、Interface、validation、validatorによる条件付き実行に関する失敗である。
|
||||||
|
|
||||||
|
- `invalid_request`
|
||||||
|
- `not_found`
|
||||||
|
- `interface_not_found`
|
||||||
|
- `operation_not_found`
|
||||||
|
- `invalid_arguments`
|
||||||
|
- `invalid_result`
|
||||||
|
- `validator_required`
|
||||||
|
- `validator_mismatch`
|
||||||
|
- `permission_denied`
|
||||||
|
- `resource_limit_exceeded`
|
||||||
|
|
||||||
|
Domain failureは、型として正しいOperationをApplicationが実行した結果として生じる失敗である。
|
||||||
|
|
||||||
|
- `issue_has_open_dependencies`
|
||||||
|
- `payment_declined`
|
||||||
|
- `merge_conflict`
|
||||||
|
|
||||||
|
Domain failureをProtocol failureへ混在させない。現在のProtocolでは、Domain failureをOperation return typeのUnion caseとして宣言する。専用のfailure declarationは定義しない。
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
# 3. Core Protocol
|
|
||||||
|
|
||||||
WIP Core Protocolは、ClientとHostの間でWorldspaceを観測・操作するための**transport-independentな意味論**を定義する。
|
|
||||||
|
|
||||||
## 3.1 役割
|
|
||||||
|
|
||||||
WIP上の主要な登場主体は**Client**と**Host**である。
|
|
||||||
|
|
||||||
### Client
|
|
||||||
|
|
||||||
ClientはHostが提供するWorldspaceをユーザーまたはAIへ提示する。
|
|
||||||
|
|
||||||
Hostから取得したエントリとInterface定義を既知の空間として保持・キャッシュし、`ref`によるObject同一性の追跡や、観測時と操作時の対応関係の検証を行う。
|
|
||||||
|
|
||||||
GUI、AI用Tools、PTC / REPL向けAPIなどへの投影はClient実装の責務とする。
|
|
||||||
|
|
||||||
### Host
|
|
||||||
|
|
||||||
HostはClientに対して一つのWorldspaceを提供する。
|
|
||||||
|
|
||||||
どのObject、エントリ、Interface、可視性を公開するかを決定し、そのClientから見えるWorldspaceを構成する。
|
|
||||||
|
|
||||||
Host内部でGitHub API、Database、Filesystem、RAG、他Agent、別プロトコルなどをどう接続・集約するかはWIPの規定対象外とする。
|
|
||||||
|
|
||||||
## 3.2 規定範囲
|
|
||||||
|
|
||||||
Core Protocolが規定するのは、ClientがHostからWorldspaceを観測し、操作するための契約である。
|
|
||||||
|
|
||||||
特定のデータソース構成、内部RPC、永続化方式、Adapter構成、同期方式は規定しない。
|
|
||||||
|
|
||||||
ClientとHostの境界は通信境界であると同時に、ある主体へどのWorldspaceを公開するかを決める信頼境界として扱える。
|
|
||||||
|
|
||||||
## 3.3 基本操作
|
|
||||||
|
|
||||||
現時点では次の4操作をCore Protocolの基本とする。
|
|
||||||
|
|
||||||
- `fetch(entry)` — 1つのエントリにあるObjectの公開情報とInterface参照を取得する。
|
|
||||||
- `fetch_tree(entry, depth, limit)` — 指定エントリを起点に、indexableな子エントリを幅優先探索してエントリツリーとして取得する。
|
|
||||||
- `fetch_interface(interface)` — Interface参照からWIP IDL documentを取得する。
|
|
||||||
- `call_operation(target, operation, arguments)` — Objectが参照するInterfaceに宣言されたOperationを実行する。
|
|
||||||
|
|
||||||
Interfaceの定義は[WIP IDL](draft/wip-idl.md) documentそのものであり、そこに宣言された関数の集合がOperation一覧となる。`call_operation`の`arguments`は選択したOperationのparameter listに従う名前付きの型付き値であり、引数がない場合は空のrecordとする。Core Protocolはこの値をJSONに限定せず、Transport Bindingが具体的なencodingを定める。
|
|
||||||
|
|
||||||
## 3.4 `fetch_tree`
|
|
||||||
|
|
||||||
`fetch_tree`は、Clientが機械的探索のために多数の`fetch`を連打することを避けるための操作である。
|
|
||||||
|
|
||||||
探索対象はindexableな子エントリのみとし、幅優先探索(BFS)で辿る。Clientは探索深度`depth`と返却エントリ総数の上限`limit`を指定できる。
|
|
||||||
|
|
||||||
探索が`depth`または`limit`によって途中で終了した場合、レスポンスは`truncated`であることを必ず明示する。Clientは取得結果を完全なツリーと誤認してはならない。
|
|
||||||
|
|
||||||
件数が非常に多いCollectionの個々の要素は、通常indexableな子エントリとして自然露出させない。必要な要素はCollection Objectの`query`や`list`等のOperationによって発見する。
|
|
||||||
|
|
||||||
## 3.5 Operation実行と発見
|
|
||||||
|
|
||||||
`call_operation`の結果は、選択したOperationのWIP IDL return typeに従う型付き値である。Return type上で`entry`として宣言された位置には、同じWorldspace内のエントリを指すcanonical absolute pathを返せる。
|
|
||||||
|
|
||||||
Clientはreturn typeに従って`entry`型の位置を認識する。通常の`string`や任意JSONに含まれるpathらしい文字列を、エントリとして推測してはならない。
|
|
||||||
|
|
||||||
返されたエントリpathのTree上の位置はOperationの実行対象から独立しており、実行対象の子に限定されない。Operationの実行対象と返されたエントリの間に、暗黙の親子関係や意味的関係を作ってはならない。
|
|
||||||
|
|
||||||
ClientはOperation結果として発見したpathを一時的に扱い、必要なものを`fetch`または`fetch_tree`して既知の空間へ統合できる。
|
|
||||||
|
|
||||||
複数の`fetch`または`fetch_interface`は、Core Protocol上ではそれぞれ独立した操作である。Transport Bindingは、個別に実行した場合と同じ意味を保ったまま、Clientが選択した複数の操作を一つのrequestへbatchしてよい。HostがClientの既知状態を推測して追加情報を先行同梱することはCore Protocolの一部としない。
|
|
||||||
|
|
||||||
## 3.6 Transportとの分離
|
|
||||||
|
|
||||||
Core ProtocolはHTTP、TCP、WebSocketなど特定のtransportを要求しない。
|
|
||||||
|
|
||||||
通信方式への具体的な対応付けはTransport Bindingとして別に定義する。標準bindingは`WIP over HTTPS`で扱う。
|
|
||||||
|
|
||||||
この分離により、Worldspaceの意味論と通信方式を独立して進化させる。
|
|
||||||
+545
@@ -0,0 +1,545 @@
|
|||||||
|
# 3. Protocol
|
||||||
|
|
||||||
|
WIP Protocolは、ClientとHostの間で交換するlogical data modelと、Core interactionのrequest / responseを定義する。
|
||||||
|
|
||||||
|
この章のstructはRust風の記法を使用するが、Rust固有のmemory layoutやserialization libraryを要求しない。TypeScriptを含む他言語でも同じ型、必須性、validation semanticsを実装できなければならない。
|
||||||
|
|
||||||
|
HTTP endpoint、JSON fieldへのencoding、status code、batch packagingはTransport Bindingの責務とし、[WIP over HTTPS](draft/wip-over-https.md)で扱う。
|
||||||
|
|
||||||
|
## Protocol dataの分類
|
||||||
|
|
||||||
|
WIPがfirst-classなprotocol dataとして定義し、Clientが取得およびcacheするものは次の二つである。
|
||||||
|
|
||||||
|
- `Object`
|
||||||
|
- `InterfaceDescriptor`
|
||||||
|
|
||||||
|
Operationのargumentsとresultには、Interface Descriptorで宣言された`Value`を使用する。Application dataは独立したWIP resourceではなく、Operation callの入力または出力として交換される。
|
||||||
|
|
||||||
|
```text
|
||||||
|
Protocol data
|
||||||
|
|-- Object
|
||||||
|
`-- InterfaceDescriptor
|
||||||
|
|
||||||
|
Operation value
|
||||||
|
|-- arguments
|
||||||
|
`-- result
|
||||||
|
```
|
||||||
|
|
||||||
|
Path、Object参照、Interface参照、validator、error等の意味は、それらが現れるfieldまたはenvelopeによって決まる。Protocol上のnamed scalarとしては定義しない。
|
||||||
|
|
||||||
|
## 記法
|
||||||
|
|
||||||
|
この章では次の記法を使用する。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct T { ... } // 名前付きfieldを持つrecord
|
||||||
|
enum T { ... } // 閉じたcaseの集合
|
||||||
|
Option<T> // 省略可能なfield
|
||||||
|
Vec<T> // 順序付きlist
|
||||||
|
BTreeMap<String, T> // string keyを持つlogical map
|
||||||
|
```
|
||||||
|
|
||||||
|
`Option<T>`はfieldの省略を表し、`null`を表さない。Transport Bindingは、省略されたfieldをwire valueへ出力してはならない。
|
||||||
|
|
||||||
|
`BTreeMap`はstring-keyed mapをRust風に示すための記法であり、keyのiteration orderをProtocol semanticsには含めない。
|
||||||
|
|
||||||
|
## Primitiveとfield semantics
|
||||||
|
|
||||||
|
Protocol structは、次のprimitiveおよびcompositeだけで表す。
|
||||||
|
|
||||||
|
```text
|
||||||
|
unit
|
||||||
|
boolean
|
||||||
|
integer
|
||||||
|
number
|
||||||
|
string
|
||||||
|
bytes
|
||||||
|
list
|
||||||
|
record
|
||||||
|
```
|
||||||
|
|
||||||
|
Path、Interface参照、Object identity、Operation名等を独立したProtocol scalarにはしない。それらは`String`または`Vec<u8>`として交換し、fieldの位置とvalidation ruleによって意味を与える。
|
||||||
|
|
||||||
|
| Field | Primitive | 解釈 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `FetchRequest.path` | `String` | rootからObjectの`name`を辿って構成したabsolute Worldspace path |
|
||||||
|
| `CallOperationRequest.target.path` | `String` | Operation対象のabsolute Worldspace path |
|
||||||
|
| `Object.interface` | `String` | Interface Descriptorへの参照 |
|
||||||
|
| `Object.ref` | `String` | 任意のopaque Object identity |
|
||||||
|
| `Object.validator` | `Vec<u8>` | HostがObjectへ付与するopaque validator |
|
||||||
|
| `CallOperationResponse.validator` | `Vec<u8>` | Operation実行後のopaque validator |
|
||||||
|
| `CallOperationRequest.operation` | `String` | Interface内のOperation名 |
|
||||||
|
|
||||||
|
同じprimitiveを使用するfieldでも意味は交換可能ではない。例えば、`Object.ref`を`FetchRequest.path`へ渡してnavigationに使用してはならない。ただし、この区別をProtocol上のnewtypeとして表す必要はない。
|
||||||
|
|
||||||
|
Rust SDKは利便性や安全性のために`Path`等のnewtypeを公開してよく、TypeScript SDKはbrand等を利用してよい。それらは言語bindingのAPIであり、Protocol structの一部ではない。
|
||||||
|
|
||||||
|
### Pathとして解釈されるstring
|
||||||
|
|
||||||
|
Pathとして宣言されたfieldのvalueは、同じWorldspace内のObjectを取得するためのcanonical absolute pathでなければならない。
|
||||||
|
|
||||||
|
- Root pathは`/`とする。
|
||||||
|
- 非root pathは、rootから対象Objectまでの各`name`を`/`で連結して構成する。
|
||||||
|
- 空segmentを含めない。
|
||||||
|
- `.`または`..`であるsegmentを含めない。
|
||||||
|
- Root以外は末尾に`/`を持たない。
|
||||||
|
- Pathに含まれる各segmentはUnicode stringとして扱い、Unicode normalizationを行わない。
|
||||||
|
- Segmentの比較はUnicode code point sequenceの完全一致で行う。
|
||||||
|
- Navigationに使用できるが、恒久的なObject identityとして使用しない。
|
||||||
|
|
||||||
|
Nameに`/`を許可しないため、Protocolはpath segment escapeを定義しない。Transport BindingによるURL encodingはWIP Pathの構成とは別に扱う。
|
||||||
|
|
||||||
|
### Opaqueな参照とvalidator
|
||||||
|
|
||||||
|
`Object.interface`と`FetchInterfaceRequest.interface`はInterface Descriptorへのopaqueな参照として解釈する。同じInterface参照が有効である間、Hostは異なるDescriptorを返してはならない。Descriptorを変更した場合は新しいInterface参照をObjectで公開する。
|
||||||
|
|
||||||
|
`Object.ref`は複数の観測にまたがって同一Objectであることを示す任意のopaque stringである。Navigationには使用せず、すべてのObjectに存在するとは限らない。Scopeと有効期間はWorldspaceまたはHost実装が定める。
|
||||||
|
|
||||||
|
`Object.validator`は、HostがそのObjectの現在状態へ付与するoptionalなopaque bytesである。Clientは内容を解釈せず、観測に基づくOperationを条件付きで実行するときに、pathとともに`target.validator`へコピーする。
|
||||||
|
|
||||||
|
Hostはvalidatorの生成方法を自由に選べる。Generation、content hash、database revision等を使用してよい。Hostは、どの状態変化によってvalidatorを無効にするかについて、そのObjectとInterfaceに対して一貫した方針を適用する。
|
||||||
|
|
||||||
|
ValidatorはAIやユーザーへ公開するApplication dataではなく、Client runtimeがObjectとともに保持するprotocol metadataである。
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Interface、Operation、type、field、parameter、caseに付与するdocumentationを次のlogical structで表す。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Documentation {
|
||||||
|
summary: String,
|
||||||
|
details: Option<String>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`summary`は一覧やSignature Viewへ短く表示する説明、`details`は明示的に展開したときに使用する説明である。
|
||||||
|
|
||||||
|
DocumentationはHostが提供するplain text dataであり、Clientのsystem instructionとして信頼しない。Transport BindingおよびClientはresource limitを適用できる。Markup、localization、構造化exampleは現在のProtocolに含めない。
|
||||||
|
|
||||||
|
## Object
|
||||||
|
|
||||||
|
`Object`は、一つのpathで現在公開されているprotocol-level projectionを表す。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Object {
|
||||||
|
name: String,
|
||||||
|
description: Option<String>,
|
||||||
|
interface: String,
|
||||||
|
r#ref: Option<String>,
|
||||||
|
validator: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `name`
|
||||||
|
|
||||||
|
親Objectの下でObjectを識別するpath segment。Root Objectの`name`は空文字列とし、非root Objectの`name`は空であってはならない。Nameに`/`を含めてはならず、Name全体が`.`または`..`であってはならない。
|
||||||
|
|
||||||
|
NameはUnicode stringとして扱い、Unicode normalizationを行わない。同じ親のchildrenは、Unicode code point sequenceの完全一致で互いに異なる`name`を持たなければならない。
|
||||||
|
|
||||||
|
### `description`
|
||||||
|
|
||||||
|
Objectが何を表すかを説明する短い公開情報。Objectの本文やApplication data全体を格納するfieldではない。
|
||||||
|
|
||||||
|
### `interface`
|
||||||
|
|
||||||
|
Objectで利用できるOperationを定義するInterface Descriptorへの参照。
|
||||||
|
|
||||||
|
### `ref`
|
||||||
|
|
||||||
|
同一Objectを複数の観測にまたがって識別するための任意のopaque identity。
|
||||||
|
|
||||||
|
### `validator`
|
||||||
|
|
||||||
|
Objectの現在状態にHostが付与する任意のopaque value。ClientはObjectとともに保持し、その観測に基づく条件付きOperationのtargetへ使用する。
|
||||||
|
|
||||||
|
`Object`はchildrenとpathを直接持たない。これらはObject identityに固有とは限らず、Objectを観測したentryまたはTree traversalのcontextに属するため、requestまたはTree responseで表す。
|
||||||
|
|
||||||
|
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である。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct InterfaceDescriptor {
|
||||||
|
format: String,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
types: Vec<TypeDeclaration>,
|
||||||
|
operations: Vec<OperationDeclaration>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Interface実装者がこのstructのJSON encodingを手書きすることは想定しない。Rust macro、TypeScript definition API、code generator等が生成し、Hostが公開する。
|
||||||
|
|
||||||
|
`types`と`operations`のdeclaration順は表示時に保持してよいが、名前解決とvalidationの結果には影響しない。
|
||||||
|
|
||||||
|
### Type declaration
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct TypeDeclaration {
|
||||||
|
name: String,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
definition: TypeExpr,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
一つのDescriptor内でType名は一意でなければならない。
|
||||||
|
|
||||||
|
### Type expression
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum TypeExpr {
|
||||||
|
Unit,
|
||||||
|
Boolean,
|
||||||
|
Integer,
|
||||||
|
Number,
|
||||||
|
String,
|
||||||
|
Bytes,
|
||||||
|
Json,
|
||||||
|
Entry,
|
||||||
|
|
||||||
|
Named {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
Record {
|
||||||
|
fields: Vec<FieldDeclaration>,
|
||||||
|
},
|
||||||
|
|
||||||
|
List {
|
||||||
|
items: Box<TypeExpr>,
|
||||||
|
},
|
||||||
|
|
||||||
|
Enum {
|
||||||
|
cases: Vec<EnumCase>,
|
||||||
|
},
|
||||||
|
|
||||||
|
Union {
|
||||||
|
cases: Vec<UnionCase>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Named`は同じInterface Descriptor内の`TypeDeclaration`を参照する。External type importとrecursive type referenceは定義しない。Descriptorの意味検証では、存在しないTypeへの参照と参照cycleを拒否する。
|
||||||
|
|
||||||
|
### Record
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct FieldDeclaration {
|
||||||
|
name: String,
|
||||||
|
required: bool,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
r#type: TypeExpr,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
一つのRecord内でfield名は一意でなければならない。`required = false`はfieldの省略を許可するが、`null`を許可する意味ではない。
|
||||||
|
|
||||||
|
Record valueに未宣言fieldが存在する場合はvalidation failureとする。
|
||||||
|
|
||||||
|
### Enum
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct EnumCase {
|
||||||
|
name: String,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Enum caseはpayloadを持たない。一つのEnum内でcase名は一意でなければならない。
|
||||||
|
|
||||||
|
### Union
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct UnionCase {
|
||||||
|
name: String,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
payload: Option<TypeExpr>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Union caseは、caseごとに0個または1個のpayloadを持つ。一つのUnion内でcase名は一意でなければならない。
|
||||||
|
|
||||||
|
### Operation declaration
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct OperationDeclaration {
|
||||||
|
name: String,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
parameters: Vec<ParameterDeclaration>,
|
||||||
|
returns: ReturnDeclaration,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ParameterDeclaration {
|
||||||
|
name: String,
|
||||||
|
required: bool,
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
r#type: TypeExpr,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ReturnDeclaration {
|
||||||
|
documentation: Option<Documentation>,
|
||||||
|
r#type: TypeExpr,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
一つのDescriptor内でOperation名は一意でなければならない。一つのOperation内でparameter名は一意でなければならない。
|
||||||
|
|
||||||
|
Interface Descriptorの生成と意味論は[2.2. Interface / Operation](2.2-operation.md)、人間とAIへのSignature Viewは[4.1. AI用Tools](4.1-ai-tools-example.md)で扱う。
|
||||||
|
|
||||||
|
## Value
|
||||||
|
|
||||||
|
Operation argumentsとresultは、schema上の意味を持たない次のlogical valueで表す。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum Value {
|
||||||
|
Unit,
|
||||||
|
Boolean(bool),
|
||||||
|
Integer(i64),
|
||||||
|
Number(f64),
|
||||||
|
String(String),
|
||||||
|
Bytes(Vec<u8>),
|
||||||
|
Record(BTreeMap<String, Value>),
|
||||||
|
List(Vec<Value>),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Value`はHostとClientが交換するprimitiveおよびcompositeだけを表す。Path、enum case、union case等のsemantic variantを持たない。既知のInterfaceに対するgenerated bindingは、言語固有DTOと`Value`のcodecを提供できる。
|
||||||
|
|
||||||
|
### Primitive semantics
|
||||||
|
|
||||||
|
| Value | 意味 | 制約 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Unit` | 値を持たない | Optional fieldの省略とは異なる |
|
||||||
|
| `Boolean` | 真偽値 | — |
|
||||||
|
| `Integer` | 符号付き整数 | `-9007199254740991`から`9007199254740991`まで |
|
||||||
|
| `Number` | IEEE 754 binary64 | NaN、正負Infinityを禁止する |
|
||||||
|
| `String` | Unicode string | — |
|
||||||
|
| `Bytes` | 任意のoctet列 | Transport Bindingがencodingを定める |
|
||||||
|
| `Record` | String keyを持つvalueの集合 | Key順に意味を持たない |
|
||||||
|
| `List` | 順序付きvalue | — |
|
||||||
|
|
||||||
|
`integer`の範囲はRustとTypeScript間でlosslessに相互運用できる範囲へ制限する。
|
||||||
|
|
||||||
|
`number`を受信したruntimeは、有限値であることを検証する。
|
||||||
|
|
||||||
|
### Descriptorによる解釈
|
||||||
|
|
||||||
|
Interface Descriptorの`TypeExpr`は、rawな`Value`に意味と追加validationを与える。
|
||||||
|
|
||||||
|
| TypeExpr | 対応するValue | 追加の解釈 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Unit` | `Value::Unit` | 値を持たないresult等 |
|
||||||
|
| `Boolean` | `Value::Boolean` | — |
|
||||||
|
| `Integer` | `Value::Integer` | 相互運用範囲を検証する |
|
||||||
|
| `Number` | `Value::Number` | 有限値を検証する |
|
||||||
|
| `String` | `Value::String` | 通常の文字列として扱う |
|
||||||
|
| `Bytes` | `Value::Bytes` | Octet列として扱う |
|
||||||
|
| `Json` | JSON data modelで表現可能なValue | 内部構造をWIP schemaとして解釈しない |
|
||||||
|
| `Entry` | `Value::String` | Canonical absolute Worldspace pathとして検証する |
|
||||||
|
| `Record` | `Value::Record` | Field declarationに従って検証する |
|
||||||
|
| `List` | `Value::List` | 各要素をitems typeに従って検証する |
|
||||||
|
| `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`と同じ範囲および有限性の制約を適用する。
|
||||||
|
|
||||||
|
`Entry`と`String`は同じprimitiveで交換する。ClientはDescriptor上で`Entry`と宣言された位置だけをWorldspace pathとして扱い、通常のStringを内容からEntryへ変換しない。
|
||||||
|
|
||||||
|
EnumもString、UnionもRecordとして交換する。SDKまたはruntimeは、Descriptorによるvalidation後の内部表現としてtyped enum、union、Path等を構築してよい。それらはProtocolの送受信形式ではない。
|
||||||
|
|
||||||
|
### Value validation
|
||||||
|
|
||||||
|
Valueは、Operation declarationのTypeExprと照合して検証する。
|
||||||
|
|
||||||
|
- `Named`を参照先Typeへ解決する。
|
||||||
|
- Required fieldまたはparameterの欠落を拒否する。
|
||||||
|
- 未宣言のRecord fieldを拒否する。
|
||||||
|
- Optional fieldの省略と`Unit`を区別する。
|
||||||
|
- EnumおよびUnionの未知caseを拒否する。
|
||||||
|
- Union discriminator、payloadの有無、payload typeをcase declarationに照合する。
|
||||||
|
- `Entry`として宣言されたStringがcanonical pathであることを検証する。
|
||||||
|
- Integerの相互運用範囲とNumberの有限性を検証する。
|
||||||
|
|
||||||
|
## `fetch`
|
||||||
|
|
||||||
|
一つのpathで現在公開されているObjectを取得する。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct FetchRequest {
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
type FetchResponse = Object;
|
||||||
|
```
|
||||||
|
|
||||||
|
Requestの`path`はresponseに重複して含めない。Root path `/`ではObjectの`name`が空文字列でなければならず、非root pathでは最後のsegmentとObjectの`name`が一致しなければならない。Clientは一致しないresponseを`InvalidResult`として扱う。
|
||||||
|
|
||||||
|
返されたObjectが`validator`を持つ場合、Clientはrequest pathとObjectを対応付けてcacheし、条件付きOperationの`target`を構築できる。Batch Transport Bindingも各itemのrequestとresponseを一意に対応付けなければならない。
|
||||||
|
|
||||||
|
## `fetch_tree`
|
||||||
|
|
||||||
|
一つのpathを起点に、indexableなObjectをBreadth-First Searchで取得する。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct FetchTreeRequest {
|
||||||
|
path: String,
|
||||||
|
depth: u32,
|
||||||
|
limit: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ObjectTreeNode {
|
||||||
|
object: Object,
|
||||||
|
children: Vec<ObjectTreeNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FetchTreeResponse {
|
||||||
|
root: ObjectTreeNode,
|
||||||
|
truncated: bool,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- 起点Objectはdepth `0`とする。
|
||||||
|
- `limit`はrootを含むresponse全体のnode数に適用する。
|
||||||
|
- Root nodeのObjectはrequest pathが指すObjectであり、Root pathが`/`でない場合は最後のsegmentとObjectの`name`が一致する。
|
||||||
|
- 各childのpathは、parent pathへchild Objectの`name`を追加して導出する。
|
||||||
|
- 同じparent nodeのchildrenは、互いに異なる`name`を持つ。
|
||||||
|
- `children`はWorldspace上の直接の子だけを含む。
|
||||||
|
- `depth`または`limit`によって存在するindexable childを省略した場合、`truncated = true`とする。
|
||||||
|
- 要求範囲内のindexable childをすべて含む場合、`truncated = false`とする。
|
||||||
|
|
||||||
|
各nodeのObjectがvalidatorを持つため、Clientはrequest pathとObjectの`name`から各pathを導出し、Treeから発見したObjectを再度`fetch`せずに条件付きOperationのtargetを構築できる。
|
||||||
|
|
||||||
|
`limit`は1以上とする。Hostはdepthとlimitへ実装上の上限を設定し、超過したrequestには`ResourceLimitExceeded`を返す。
|
||||||
|
|
||||||
|
## `fetch_interface`
|
||||||
|
|
||||||
|
Interface参照に対応するInterface Descriptorを取得する。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct FetchInterfaceRequest {
|
||||||
|
interface: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FetchInterfaceResponse {
|
||||||
|
interface: String,
|
||||||
|
descriptor: InterfaceDescriptor,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Clientは次を検証する。
|
||||||
|
|
||||||
|
- Responseの`interface`がrequestと一致する。
|
||||||
|
- Descriptorが構造検証および意味検証に成功する。
|
||||||
|
- Descriptorの`format`がClientの対応するversionである。
|
||||||
|
|
||||||
|
Interface参照はHostが発行するopaque stringである。Clientは参照をcache keyとして使用し、同じ有効な参照から異なるDescriptorを受け取った場合はProtocol failureとして扱う。
|
||||||
|
|
||||||
|
## `call_operation`
|
||||||
|
|
||||||
|
指定pathにあるObjectへOperationを実行する。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Target {
|
||||||
|
path: String,
|
||||||
|
validator: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CallOperationRequest {
|
||||||
|
target: Target,
|
||||||
|
operation: String,
|
||||||
|
arguments: BTreeMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CallOperationResponse {
|
||||||
|
result: Value,
|
||||||
|
validator: Option<Vec<u8>>,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`target.path`はOperationを実行するObjectのpathである。`target.validator`は、Clientが観測したObjectのvalidatorを条件として指定する。Validatorを持たないObjectまたは無条件実行では省略する。
|
||||||
|
|
||||||
|
`arguments`はOperation parameterに対応する名前付きrecordである。引数がない場合は空のmapを送る。
|
||||||
|
|
||||||
|
`target.validator`が指定された場合、Hostは現在のvalidatorとの比較とOperation実行をatomicに行う。一致しない場合はOperationを実行せず`ValidatorMismatch`を返す。Hostがvalidatorを要求するOperationに指定がない場合は`ValidatorRequired`を返す。
|
||||||
|
|
||||||
|
Hostはvalidatorの生成方法と無効化する状態変化を決定する。Content hash、generation、database revision等を使用できる。比較はopaque bytesの完全一致で行う。
|
||||||
|
|
||||||
|
Responseの`validator`はOperation実行後の現在状態に対してHostが発行した値である。Read-only Operationでもresultを観測した時点のvalidatorを返してよい。Validatorを提供しない場合は省略する。
|
||||||
|
|
||||||
|
ClientはresultをOperationのreturn typeに従って検証する。Validationに失敗したvalueをApplicationへ渡さない。
|
||||||
|
|
||||||
|
## Protocol responseとfailure
|
||||||
|
|
||||||
|
Core interactionは、成功responseまたはProtocol failureを返す。
|
||||||
|
|
||||||
|
```rust
|
||||||
|
enum ProtocolResult<T> {
|
||||||
|
Success(T),
|
||||||
|
Failure(ProtocolError),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProtocolError {
|
||||||
|
code: ProtocolErrorCode,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ProtocolErrorCode {
|
||||||
|
InvalidRequest,
|
||||||
|
NotFound,
|
||||||
|
InterfaceNotFound,
|
||||||
|
OperationNotFound,
|
||||||
|
InvalidArguments,
|
||||||
|
InvalidResult,
|
||||||
|
ValidatorRequired,
|
||||||
|
ValidatorMismatch,
|
||||||
|
PermissionDenied,
|
||||||
|
ResourceLimitExceeded,
|
||||||
|
Internal,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`message`は人間向けのboundedな診断であり、Clientが分岐に使用する安定した値ではない。Clientは`code`を使用する。
|
||||||
|
|
||||||
|
Hostは情報漏洩を避けるため、存在するが閲覧できないObjectに`NotFound`を返してもよい。
|
||||||
|
|
||||||
|
Protocol failureとdomain failureを混在させない。現在のProtocolでは、Domain failureをApplicationのOperation resultに含まれるUnion caseとして明示する。専用のfailure envelopeは定義しない。
|
||||||
|
|
||||||
|
Transport BindingはProtocol Resultをstatus code、response envelope、stream termination等へ対応付ける。
|
||||||
|
|
||||||
|
## Resource limit
|
||||||
|
|
||||||
|
HostとClientは、untrusted inputによるresource exhaustionを避けるため、少なくとも次へ上限を設ける。
|
||||||
|
|
||||||
|
- Pathとして解釈するstring、validator、name、description、documentationの長さ。
|
||||||
|
- Interface Descriptor全体のbyte数。
|
||||||
|
- Type declaration、Operation、parameter、field、caseの数。
|
||||||
|
- TypeExprとValueのnesting depth。
|
||||||
|
- Record field数とList要素数。
|
||||||
|
- `fetch_tree`のdepthとlimit。
|
||||||
|
- Protocol error messageの長さ。
|
||||||
|
|
||||||
|
各実装はこれらにboundedな上限を設定する。上限を超えたrequestまたはresponseは`ResourceLimitExceeded`として扱い、現在のProtocolではlimit negotiationを定義しない。
|
||||||
|
|
||||||
|
## Batch
|
||||||
|
|
||||||
|
BatchはCore interactionではなくTransport Bindingのoptimizationである。
|
||||||
|
|
||||||
|
Transport Bindingは、複数の`FetchRequest`、`FetchTreeRequest`、`FetchInterfaceRequest`を一つのphysical requestへまとめてよい。それぞれのlogical requestは独立して成功または失敗し、個別に実行した場合と同じ意味を持たなければならない。
|
||||||
|
|
||||||
|
`call_operation`は副作用、順序、部分的成功の意味が不明確になるため、Coreの標準batch対象にしない。
|
||||||
|
|
||||||
|
## Transport Bindingの要件
|
||||||
|
|
||||||
|
Transport Bindingは、この章のlogical structについて次を定義する。
|
||||||
|
|
||||||
|
- Requestとresponseのframing。
|
||||||
|
- Protocol primitiveのconcrete encoding。
|
||||||
|
- Object、Descriptor、Valueのencoding。
|
||||||
|
- Optional fieldの省略。
|
||||||
|
- Protocol failureのmapping。
|
||||||
|
- Validatorのmapping。
|
||||||
|
- Batch packagingを提供する場合はitemの対応付けと部分的failure。
|
||||||
|
- Message size、timeout、concurrency等のtransport固有limit。
|
||||||
|
|
||||||
|
Transport Bindingは、logical typeの区別またはvalidation semanticsを失ってはならない。
|
||||||
+6
-6
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 役割
|
## 役割
|
||||||
|
|
||||||
Clientは、Hostが提供するWorldspaceをユーザーへ提示する実装主体である。WIPのCore Protocolを直接利用しつつ、Objectが参照するInterfaceを解決し、用途に応じたViewやAPIへ投影する。
|
Clientは、Hostが提供するWorldspaceをユーザーへ提示する実装主体である。WIP Protocolを利用しつつ、Objectが参照するInterfaceを解決し、用途に応じたViewやAPIへ投影する。
|
||||||
|
|
||||||
ClientはHostから得た情報をそのまま一時表示するだけでなく、rootからindexable edgeを辿って構成したエントリツリーと、必要に応じて選択したエントリを保持し、ユーザーから見た**既知の空間**を構成する。
|
ClientはHostから得た情報をそのまま一時表示するだけでなく、rootからindexable edgeを辿って構成したエントリツリーと、必要に応じて選択したエントリを保持し、ユーザーから見た**既知の空間**を構成する。
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@ Operationを通して発見されたpathは、必ずしもKnown Spaceへ追加
|
|||||||
|
|
||||||
## Interface cache
|
## Interface cache
|
||||||
|
|
||||||
Objectの公開情報はOperation定義を直接含まず、Interface参照を持つ。Clientは未知のInterface参照を`fetch_interface`で解決し、取得したWIP IDL documentを参照ごとにcacheする。
|
Objectの公開情報はOperation定義を直接含まず、Interface参照を持つ。Clientは未知のInterface参照を`fetch_interface`で解決し、取得したInterface Descriptorを参照ごとにcacheする。
|
||||||
|
|
||||||
一つのInterface documentに宣言された関数の集合が、そのInterfaceのOperation一覧である。複数のObjectが同じInterfaceを参照する場合、ClientはIDLを一度だけ取得・parseすればよい。
|
一つのInterface Descriptorに宣言されたOperationの集合が、そのInterfaceのOperation一覧である。複数のObjectが同じInterfaceを参照する場合、ClientはDescriptorを一度だけ取得、検証すればよい。
|
||||||
|
|
||||||
ClientはInterface cacheとObjectのInterface参照を比較し、未知のInterfaceだけを取得する。複数の`fetch_interface`は、Transport Bindingが提供するbatchを利用してまとめてよい。
|
ClientはInterface cacheとObjectのInterface参照を比較し、未知のInterfaceだけを取得する。複数の`fetch_interface`は、Transport Bindingが提供するbatchを利用してまとめてよい。
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ Clientは、Operation Resultの`entry`型として発見したpathを現在の
|
|||||||
|
|
||||||
一時的に取得したエントリは、結果の利用が終わった時点で破棄してよい。
|
一時的に取得したエントリは、結果の利用が終わった時点で破棄してよい。
|
||||||
|
|
||||||
後続のInteractionでも必要なエントリは、Client側でpinしてKnown Spaceへ保持できる。PinはClient内部の保持方針であり、Host上のObject lifetimeやCore Protocol上の状態を変更しない。
|
後続のInteractionでも必要なエントリは、Client側でpinしてKnown Spaceへ保持できる。PinはClient内部の保持方針であり、Host上のObject lifetimeやWIP Protocol上の状態を変更しない。
|
||||||
|
|
||||||
単純なClientは発見したエントリをすべて保持してもよいが、WIPはそれを必須としない。具体的な容量制限やeviction algorithmはClient実装に委ねる。
|
単純なClientは発見したエントリをすべて保持してもよいが、WIPはそれを必須としない。具体的な容量制限やeviction algorithmはClient実装に委ねる。
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ Clientは、Operation Resultの`entry`型として発見したpathを現在の
|
|||||||
|
|
||||||
Clientは、機械的にエントリを探索する必要がある場合、個別の`fetch`を多数発行するのではなく`fetch_tree`を利用する。
|
Clientは、機械的にエントリを探索する必要がある場合、個別の`fetch`を多数発行するのではなく`fetch_tree`を利用する。
|
||||||
|
|
||||||
`fetch_tree`では起点エントリ、探索深度`depth`、返却エントリ総数の上限`limit`を指定する。Hostはindex edgeを幅優先探索してTreeを返す。
|
`fetch_tree`では起点path、探索深度`depth`、返却エントリ総数の上限`limit`を指定する。Hostはindex edgeを幅優先探索してTreeを返す。Tree nodeはpathを重複して持たず、Clientは起点pathと各Objectの`name`からchild pathを導出する。
|
||||||
|
|
||||||
レスポンスが`truncated`である場合、Clientは取得したTreeが完全ではないことを保持し、完全な空間として扱ってはならない。
|
レスポンスが`truncated`である場合、Clientは取得したTreeが完全ではないことを保持し、完全な空間として扱ってはならない。
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ Objectが`ref`を公開している場合、Clientはそれを用いて複数の
|
|||||||
|
|
||||||
Clientは、エントリを観測した後にOperationを実行するまでの間に、そのエントリが別Objectを指すようになっていないことを検証する責務を持つ。
|
Clientは、エントリを観測した後にOperationを実行するまでの間に、そのエントリが別Objectを指すようになっていないことを検証する責務を持つ。
|
||||||
|
|
||||||
この検証に必要なopaque token、generation、ETag等はClient / Host間で透過的に扱い、AIやユーザーに直接管理させる必要はない。
|
Objectが`validator`を持つ場合、Clientは観測したpathとvalidatorを対応付ける。条件付きOperationでは両者をtargetとしてHostへ渡し、validatorの比較と実行をHost上でatomicに行わせる。ValidatorはAIやユーザーに直接管理させない。HTTPS Bindingは、semanticsが適合する場合にHTTP ETag等へ対応付けてよい。
|
||||||
|
|
||||||
対象が変化していた場合、Clientは新しいObjectに対してOperationを自動再試行せず、対象が変化したことを上位インターフェースへ通知して再観測を要求する。
|
対象が変化していた場合、Clientは新しいObjectに対してOperationを自動再試行せず、対象が変化したことを上位インターフェースへ通知して再観測を要求する。
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## 目的
|
## 目的
|
||||||
|
|
||||||
AI用Toolsは、WIP ClientがAIへ提供する想定インターフェースである。Core Protocolをそのまま露出せず、Clientが保持するKnown Space / Discoverable Spaceと組み合わせて、AIがWorldspaceを理解・探索・操作しやすい形へ投影する。
|
AI用Toolsは、WIP ClientがAIへ提供する想定インターフェースである。Protocol structをそのまま露出せず、Clientが保持するKnown Space / Discoverable Spaceと組み合わせて、AIがWorldspaceを理解・探索・操作しやすい形へ投影する。
|
||||||
|
|
||||||
現時点では、**discover / inspect / invoke** の3操作を基本とする。
|
現時点では、**discover / inspect / invoke** の3操作を基本とする。
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ AI用Toolsは、WIP ClientがAIへ提供する想定インターフェースで
|
|||||||
|
|
||||||
## `inspect`
|
## `inspect`
|
||||||
|
|
||||||
`inspect(target)` は、対象エントリ / Objectについて**何ができるか**を把握するための操作である。ClientはObjectのInterface参照を解決し、WIP IDL documentに宣言されたOperationを提示する。
|
`inspect(target)` は、対象エントリ / Objectについて**何ができるか**を把握するための操作である。ClientはObjectのInterface参照を解決し、Interface Descriptorに宣言されたOperationを提示する。
|
||||||
|
|
||||||
Objectのドメインデータをpropertiesとして直接公開することは前提としない。データを読む行為もOperationとして表現する。
|
Objectのドメインデータをpropertiesとして直接公開することは前提としない。データを読む行為もOperationとして表現する。
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ Objectのドメインデータをpropertiesとして直接公開することは
|
|||||||
- `get_related_items()` — 関連Objectのentry pathを取得する。
|
- `get_related_items()` — 関連Objectのentry pathを取得する。
|
||||||
- `close(reason: string)` — 理由を添えてIssueをクローズする。
|
- `close(reason: string)` — 理由を添えてIssueをクローズする。
|
||||||
|
|
||||||
Operationの関数宣言と短いdocumentationは、Objectが参照する[WIP IDL](draft/wip-idl.md) documentから取得する。ClientはIDLをparseし、利用するAI providerが要求するTool schemaへ変換する。JSON Schema等への変換はAI向けClient adapterの責務であり、HostがWIP Interfaceとして提供する必要はない。
|
Operationの関数宣言と短いdocumentationは、Objectが参照する[Interface Descriptor](2.2-operation.md)から取得する。Clientは検証済みDescriptorからIDL風のSignature Viewを生成し、人間とAIへ提示する。利用するAI providerがTool schemaを要求する場合、Client adapterがDescriptorからJSON Schema等へ変換する。Provider固有schemaをHostがWIP Interfaceとして提供する必要はない。
|
||||||
|
|
||||||
## `invoke`
|
## `invoke`
|
||||||
|
|
||||||
`invoke(target, operation, arguments)` は、`inspect`によって発見したOperationを実行する。`arguments`はOperationのWIP IDL parameter listに従う名前付きfieldのrecordであり、位置引数は用いない。引数を持たないOperationには空のrecordを渡す。
|
`invoke(target, operation, arguments)` は、`inspect`によって発見したOperationを実行する。`arguments`はOperationのparameter declarationに従う名前付きfieldのrecordであり、位置引数は用いない。引数を持たないOperationには空のrecordを渡す。Clientはargumentsを検証し、対象pathと観測したObjectのoptionalなvalidatorから`call_operation`のtargetを構築する。
|
||||||
|
|
||||||
PTC / REPL bindingでは、通常のメソッド呼び出しへ投影してよい。
|
PTC / REPL bindingでは、通常のメソッド呼び出しへ投影してよい。
|
||||||
|
|
||||||
|
|||||||
+37
-17
@@ -1,36 +1,56 @@
|
|||||||
# 未解決事項
|
# 未解決事項
|
||||||
|
|
||||||
各設計ページに未解決事項を分散させず、このページで対象ページとともに一元管理する。
|
主要な未解決事項を、canonicalなCore文書とTransport Bindingへのindexとしてまとめる。
|
||||||
|
|
||||||
## 2.1. Object tree / Schema
|
## 2.1. Object tree / Schema
|
||||||
|
|
||||||
対象: [2.1. Object tree / Schema](../2.1-object-tree-schema.md)
|
対象: [2.1. Object tree / Schema](../2.1-object-tree-schema.md)
|
||||||
|
|
||||||
- Object / エントリ公開情報とInterface参照の具体的なwire schema。
|
- 一つのObjectが複数pathへ配置された場合、`description`をObject固有または配置固有のどちらとするか。
|
||||||
- `name`とpath segmentの関係。
|
- Partial visibility、redaction、authorization failureの表現。
|
||||||
- entry pathのcanonicalization規則。
|
|
||||||
- Object `description`の長さや必須性をprotocol上でどこまで規定するか。
|
|
||||||
|
|
||||||
## 2.2. Operation / WIP IDL
|
## 2.2. Interface / Operation
|
||||||
|
|
||||||
対象: [2.2. Operation](../2.2-operation.md)、[WIP IDL](wip-idl.md)
|
対象: [2.2. Interface / Operation](../2.2-operation.md)
|
||||||
|
|
||||||
|
- RustとTypeScriptのcode-level Interface Declaration API。
|
||||||
|
- Interface参照をcontent-addressedにし、Descriptor digestをProtocolへ導入するか。
|
||||||
|
- Descriptor version間の互換性規則。
|
||||||
|
- 現在plain textであるDocumentationへmarkup、localization、構造化exampleを追加するか。
|
||||||
|
- Signature Viewのfull renderingをどこまで標準化するか。
|
||||||
|
- Effect annotationを採用するか。
|
||||||
|
- 現在Unionで表すDomain failureへ専用declarationを追加するか。
|
||||||
|
|
||||||
|
## 3. Protocol
|
||||||
|
|
||||||
|
対象: [3. Protocol](../3-protocol.md)
|
||||||
|
|
||||||
|
### Field semantics
|
||||||
|
|
||||||
|
- `ref` fieldのencoding、scope、有効期間。
|
||||||
|
- `interface` fieldで使用するopaque参照のscopeと有効期間。
|
||||||
|
- Validatorの生成、期限、再利用、およびObjectごとの無効化方針をどこまで標準化するか。
|
||||||
|
|
||||||
|
### Type / Value
|
||||||
|
|
||||||
- WIP IDL sourceのcanonicalization、digest algorithm、Interface参照の形式とscope。
|
|
||||||
- WIP IDLのversion間における互換性規則。
|
|
||||||
- String length、numeric range、pattern等のconstraintを導入するか。
|
- String length、numeric range、pattern等のconstraintを導入するか。
|
||||||
- Recursive named typeを許可するか。
|
- 現在拒否するrecursive named typeを許可するか。
|
||||||
- `i64`、`u64`、`bigint`、`decimal`等を追加するか。
|
- `i64`、`u64`、`bigint`、`decimal`等を追加するか。
|
||||||
- Operation documentationの必須性と長さ。
|
- `json` escape hatchをすべてのTransport Bindingへ要求するか。
|
||||||
- Effect annotationを採用するか、および構文と標準effectの集合。
|
|
||||||
- `fail<E>`を採用する場合のdomain failure表現。
|
### Interaction / Error
|
||||||
- domain errorをOperationのreturn typeに含めるか、Protocol errorとして分離するか。
|
|
||||||
|
- `fetch_tree`のdepthとlimitへ相互運用上の共通上限を定義するか。
|
||||||
|
- ProtocolErrorへstructured detailを追加するか。
|
||||||
|
- Resource limitを固定値またはcapability negotiationのどちらで定義するか。
|
||||||
|
|
||||||
## WIP over HTTPS
|
## WIP over HTTPS
|
||||||
|
|
||||||
対象: [WIP over HTTPS](wip-over-https.md)
|
対象: [WIP over HTTPS](wip-over-https.md)
|
||||||
|
|
||||||
- `fetch_interface`のrequest / response wire schema。
|
- Protocol primitive、Object、Interface Descriptor、ValueのJSON encoding。
|
||||||
- Effect annotationを採用した場合に、副作用のない`call_operation`をbatch対象へ加えるか。
|
- Validatorをresponse body、HTTP ETag / If-Match、または両方へどうmappingするか。
|
||||||
|
- Protocol failureのHTTP statusとerror body。
|
||||||
- Batch件数、request / response byte size、timeoutの上限。
|
- Batch件数、request / response byte size、timeoutの上限。
|
||||||
- Batch envelope自体が不正な場合のHTTP statusとerror body。
|
- Batch envelope自体が不正な場合のHTTP statusとerror body。
|
||||||
- Subrequest共通のProtocol error schema。
|
- Effect annotationを採用した場合に、副作用のない`call_operation`をbatch対象へ加えるか。
|
||||||
|
|||||||
@@ -1,335 +0,0 @@
|
|||||||
# WIP IDL
|
|
||||||
|
|
||||||
WIP IDLは、Objectが実装するInterfaceを記述するための小さなinterface definition languageである。
|
|
||||||
|
|
||||||
一つのWIP IDL documentが一つのInterfaceを定義する。Documentに宣言された関数の集合が、そのInterfaceのOperation集合となる。Operation名、parameter、return type、documentationはIDL内の一つの宣言としてまとめ、別のOperation descriptorへ重複して記述しない。
|
|
||||||
|
|
||||||
WIP IDLのsourceそのものをInterface定義のcanonicalな交換形式とする。HostとClientの間でJSON SchemaやIDLを変換したJSON ASTを交換することは前提としない。Clientはsourceをparseして内部表現を構築し、必要に応じてAI Tool schemaやGUI formへ投影する。
|
|
||||||
|
|
||||||
この文書では、WIP IDLの初期文法と型を定義する。
|
|
||||||
|
|
||||||
## 設計方針
|
|
||||||
|
|
||||||
- 一つのdocumentで一つのInterfaceを定義する。
|
|
||||||
- Document内のOperation declarationを、そのInterfaceのOperation一覧とする。
|
|
||||||
- Operationを関数として、parameterとreturn typeを一体で表現する。
|
|
||||||
- 文法を小さく保ち、一般的なschema validation languageにはしない。
|
|
||||||
- Wire上の値表現はTransport Bindingが定める。
|
|
||||||
- JSON SchemaはWIPの交換形式にせず、必要なClientが生成する。
|
|
||||||
- Worldspaceのエントリは、そのpathを表す`entry`型として扱う。
|
|
||||||
|
|
||||||
## Source
|
|
||||||
|
|
||||||
WIP IDL sourceはUTF-8 textとする。ASCII space、tab、LFによる空白は、tokenを分離する場合を除いて意味を持たない。
|
|
||||||
|
|
||||||
`//`から行末までは通常のcommentとし、parserは無視する。
|
|
||||||
|
|
||||||
`///`から行末まではdocumentation commentとする。Operationまたはtype declarationの直前に連続するdocumentation commentは、そのdeclarationのdocumentationとしてparserが保持する。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
/// Returns entries related to the target Object.
|
|
||||||
operation get_related_items() -> {
|
|
||||||
items: [entry],
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
IdentifierはASCIIの英字または`_`で始まり、以降にASCIIの英数字または`_`を含められる。
|
|
||||||
|
|
||||||
```text
|
|
||||||
identifier = (ALPHA | "_") { ALPHA | DIGIT | "_" };
|
|
||||||
```
|
|
||||||
|
|
||||||
Keyword、primitive type名、Worldspace固有型名はidentifierとして使用できない。
|
|
||||||
|
|
||||||
Named typeにはUpperCamelCase、Operation、parameter、field、enum case、union caseにはsnake_caseを使用する。
|
|
||||||
|
|
||||||
## Grammar
|
|
||||||
|
|
||||||
以下のEBNFは空白とcommentを省略して示す。
|
|
||||||
|
|
||||||
```ebnf
|
|
||||||
document = { declaration } ;
|
|
||||||
|
|
||||||
declaration = [ documentation ],
|
|
||||||
( type-declaration | operation-declaration ) ;
|
|
||||||
|
|
||||||
documentation = doc-comment, { doc-comment } ;
|
|
||||||
|
|
||||||
type-declaration = "type", type-name, "=", type-definition, ";" ;
|
|
||||||
|
|
||||||
type-definition = type-expression | enum-type | union-type ;
|
|
||||||
|
|
||||||
operation-declaration =
|
|
||||||
"operation", identifier,
|
|
||||||
"(", [ parameter, { ",", parameter }, [ "," ] ], ")",
|
|
||||||
"->", type-expression, ";" ;
|
|
||||||
|
|
||||||
parameter = identifier, [ "?" ], ":", type-expression ;
|
|
||||||
|
|
||||||
type-expression =
|
|
||||||
primitive-type
|
|
||||||
| worldspace-type
|
|
||||||
| type-name
|
|
||||||
| record-type
|
|
||||||
| list-type ;
|
|
||||||
|
|
||||||
record-type =
|
|
||||||
"{", [ record-field, { ",", record-field }, [ "," ] ], "}" ;
|
|
||||||
|
|
||||||
record-field = identifier, [ "?" ], ":", type-expression ;
|
|
||||||
|
|
||||||
list-type = "[", type-expression, "]" ;
|
|
||||||
|
|
||||||
enum-type =
|
|
||||||
"enum", "{", identifier, { ",", identifier }, [ "," ], "}" ;
|
|
||||||
|
|
||||||
union-type =
|
|
||||||
"union", "{", union-case, { ",", union-case }, [ "," ], "}" ;
|
|
||||||
|
|
||||||
union-case = identifier, [ "(", type-expression, ")" ] ;
|
|
||||||
|
|
||||||
primitive-type =
|
|
||||||
"unit"
|
|
||||||
| "boolean"
|
|
||||||
| "integer"
|
|
||||||
| "number"
|
|
||||||
| "string"
|
|
||||||
| "bytes"
|
|
||||||
| "json" ;
|
|
||||||
|
|
||||||
worldspace-type = "entry" ;
|
|
||||||
|
|
||||||
type-name = identifier ;
|
|
||||||
```
|
|
||||||
|
|
||||||
同じdocument内でtype名またはOperation名を重複して宣言してはならない。同じOperation内でparameter名を重複してはならない。Named typeは同じdocument内で宣言されたtypeを参照する。
|
|
||||||
|
|
||||||
## Primitive types
|
|
||||||
|
|
||||||
| Type | 意味 | WIP over HTTPSでの表現 | 制約 |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| `unit` | 値を持たない | JSON `null` | Optional parameter / fieldの省略とは区別する |
|
|
||||||
| `boolean` | 真偽値 | JSON boolean | — |
|
|
||||||
| `integer` | 符号付き整数 | 小数部を持たないJSON number | `-9007199254740991`以上、`9007199254740991`以下 |
|
|
||||||
| `number` | IEEE 754 binary64値 | JSON number | NaN、positive infinity、negative infinityは不可 |
|
|
||||||
| `string` | Unicode string | JSON string | — |
|
|
||||||
| `bytes` | 任意のoctet列 | RFC 4648 Section 4のbase64を格納したJSON string | paddingを含む |
|
|
||||||
| `json` | opaqueな任意のJSON value | JSON value | Clientは内部構造をschemaとして解釈しない |
|
|
||||||
|
|
||||||
`integer`の範囲は、異なる言語のClient間で正確に交換できる範囲に制限している。この範囲を超える整数は`integer`としてencodeしない。`i64`、`u64`、`bigint`等の追加型とlosslessなwire表現は将来の拡張として扱う。
|
|
||||||
|
|
||||||
`json`は外部APIの応答など構造を事前に固定できない値のためのescape hatchであり、通常のOperationではより具体的な型を優先する。
|
|
||||||
|
|
||||||
## Composite types
|
|
||||||
|
|
||||||
| Type | 構文 | 意味 | WIP over HTTPSでの表現 |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| Record | `{ field: Type }` | 名前付きfieldの集合 | JSON object |
|
|
||||||
| List | `[Type]` | 同じ型の順序付き値 | JSON array |
|
|
||||||
| Named type | `type Name = Type;` | 型への名前付け | 参照先と同じ表現 |
|
|
||||||
| Enum | `enum { first, second }` | payloadを持たないcaseの集合 | case名のJSON string |
|
|
||||||
| Union | `union { case(Type), empty }` | discriminatorを持つcaseの集合 | `$case`を持つJSON object |
|
|
||||||
|
|
||||||
### Record
|
|
||||||
|
|
||||||
Recordは名前付きfieldの集合である。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
type QueryResult = {
|
|
||||||
items: [entry],
|
|
||||||
next_cursor?: string,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
`?`を持たないfieldはrequired、`?`を持つfieldはoptionalである。Optionalはparameterまたはrecord fieldにのみ適用し、一般化しない。
|
|
||||||
|
|
||||||
WIP over HTTPSではrecordをJSON objectとしてencodeする。Optional fieldに値がない場合はfield自体を省略する。FieldをJSON `null`にすることは省略と同じ意味ではなく、そのfieldの型が`unit`または`json`として`null`を許す場合に限る。
|
|
||||||
|
|
||||||
宣言されていないfieldをrecordに含めてはならない。
|
|
||||||
|
|
||||||
### List
|
|
||||||
|
|
||||||
Listは同じ型の0個以上の順序付き値を表す。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
[entry]
|
|
||||||
```
|
|
||||||
|
|
||||||
WIP over HTTPSではJSON arrayとしてencodeする。
|
|
||||||
|
|
||||||
### Named type
|
|
||||||
|
|
||||||
`type`宣言によって型へ名前を付けられる。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
type IssueList = [entry];
|
|
||||||
```
|
|
||||||
|
|
||||||
Aliasを参照する値のwire表現は、参照先の型と同じである。
|
|
||||||
|
|
||||||
### Enum
|
|
||||||
|
|
||||||
Enumはpayloadを持たないcaseの集合である。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
type Relation = enum {
|
|
||||||
parent,
|
|
||||||
sibling,
|
|
||||||
related,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
WIP over HTTPSではcase名をJSON stringとしてencodeする。
|
|
||||||
|
|
||||||
```json
|
|
||||||
"sibling"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Union
|
|
||||||
|
|
||||||
Unionはdiscriminatorを持つcaseの集合である。Caseは0個または1個のpayloadを持つ。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
type LookupResult = union {
|
|
||||||
found(entry),
|
|
||||||
not_found,
|
|
||||||
ambiguous([entry]),
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
WIP over HTTPSでは`$case` discriminatorを持つJSON objectとしてencodeする。Payloadを持つcaseは`value` fieldに値を格納する。
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$case": "found",
|
|
||||||
"value": "/items/123"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Payloadを持たないcaseには`value`を含めない。
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$case": "not_found"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Worldspace type
|
|
||||||
|
|
||||||
| Type | 意味 | WIP over HTTPSでの表現 |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `entry` | 同じWorldspace内のエントリを指すcanonical absolute path | JSON string |
|
|
||||||
|
|
||||||
```json
|
|
||||||
"/items/123"
|
|
||||||
```
|
|
||||||
|
|
||||||
Wire上では通常の`string`と同じ表現だが、WIP IDL上で`entry`と宣言された位置にある値だけをClientがエントリとして認識する。通常の`string`やopaqueな`json`に含まれるpathらしい文字列を、Clientがエントリとして推測してはならない。
|
|
||||||
|
|
||||||
Operation Resultから`entry`を発見したClientは、そのpathを一時的に利用し、必要に応じて`fetch`または`fetch_tree`する。複数のpathを効率的に取得する場合は、Clientが必要なpathを選択した後、Transport Bindingが提供するbatchを利用する。Operation Resultへエントリ公開情報を先行同梱しない。
|
|
||||||
|
|
||||||
Operationが返したpathは、Operationの実行対象の子に限定されない。親、兄弟、関連Objectなど、Worldspace内の任意のエントリを指してよい。Operationの実行対象と返されたpathの間に、暗黙のTree edgeや意味的関係を推論してはならない。
|
|
||||||
|
|
||||||
`fetch`が返すエントリ公開情報と、`fetch_tree`が返すindexableなtreeはCore Protocolのresponseであり、WIP IDLの値型としては定義しない。
|
|
||||||
|
|
||||||
## Operation declarations
|
|
||||||
|
|
||||||
Operationは名前付きparameterとreturn typeを一つの関数宣言として定義する。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
type Relation = enum {
|
|
||||||
parent,
|
|
||||||
sibling,
|
|
||||||
related,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Returns entries related to the target Object.
|
|
||||||
operation get_related_items(
|
|
||||||
relation: Relation,
|
|
||||||
limit?: integer,
|
|
||||||
) -> {
|
|
||||||
items: [entry],
|
|
||||||
next_cursor?: string,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
Operationのparameterは、WIP over HTTPSでは一つのJSON objectへencodeする。Parameter名がobjectのfield名になる。位置引数は定義しない。
|
|
||||||
|
|
||||||
引数を持たないOperationは空のparameter listで宣言し、空のJSON objectをargumentsとして渡す。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
operation refresh() -> unit;
|
|
||||||
```
|
|
||||||
|
|
||||||
Return typeには任意のtype expressionまたはNamed typeを使用できる。ただし、将来fieldを追加する可能性があるOperationではrecordを推奨する。
|
|
||||||
|
|
||||||
`///` documentation commentは、AIやユーザーがOperationの用途を判断するための短いdescriptionとして扱う。長文documentationをIDLへ埋め込むことは想定しない。
|
|
||||||
|
|
||||||
## Effect annotation(検討案)
|
|
||||||
|
|
||||||
Operationがdomain-levelな副作用や失敗を発生させ得ることを、関数宣言上のeffect rowとして表す案を検討する。この節は確定仕様ではなく、前掲のEBNFにもまだ含めない。
|
|
||||||
|
|
||||||
構文は、return typeの後に`! { ... }`を付ける形を候補とする。
|
|
||||||
|
|
||||||
```wip
|
|
||||||
operation get_item(
|
|
||||||
id: string,
|
|
||||||
) -> Item ! {};
|
|
||||||
|
|
||||||
operation update_item(
|
|
||||||
id: string,
|
|
||||||
value: Item,
|
|
||||||
) -> Item ! {
|
|
||||||
write,
|
|
||||||
fail<UpdateError>,
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
| Annotation | 意味の候補 |
|
|
||||||
| --- | --- |
|
|
||||||
| `! {}` | 宣言上、domain-levelな副作用およびfailureを持たない |
|
|
||||||
| `write` | 外部から観測可能な副作用を発生させ得る |
|
|
||||||
| `fail<E>` | `E`型のdomain failureを返し得る |
|
|
||||||
| annotationなし | Effect情報が未指定 |
|
|
||||||
|
|
||||||
Network error、authorization失敗、target消失、Protocol decode errorなど、すべてのremote callで起こり得るProtocol errorは`fail<E>`に含めない。`fail<E>`はOperation固有のdomain failureだけを表す候補とする。
|
|
||||||
|
|
||||||
Effect annotationは、ClientによるOperationの説明や、HTTP batchへ安全に含められるOperationの判定材料として利用できる可能性がある。ただし、具体的なbatch可否規則はまだ確定しない。
|
|
||||||
|
|
||||||
この案はKokaのeffect rowやUnisonのability requirementのように、関数が起こし得るeffectをsignatureへ表す記法を参考にしている。ただしWIP IDLへ導入するのは宣言上のannotationだけであり、effect handler、`perform`、continuation、resume、handlerへのnetwork転送、algebraic effect runtimeは導入しない。
|
|
||||||
|
|
||||||
## Interface identity and sharing
|
|
||||||
|
|
||||||
一つのWIP IDL documentが一つのInterfaceを定義する。ObjectはOperation定義ではなく、そのInterfaceへの参照を持つ。
|
|
||||||
|
|
||||||
複数のObjectが同じInterface参照を共有できる。Clientは未知のInterfaceだけを`fetch_interface`で取得し、参照ごとにIDL sourceとparse済み表現をcacheできる。
|
|
||||||
|
|
||||||
Hostは主体のroleや権限に応じて異なるOperation集合を投影する場合、異なるWIP IDL documentとInterface参照を返してよい。Interfaceは頻繁に変化するOperationの実行可否を表すものではない。
|
|
||||||
|
|
||||||
Interface参照をcontent-addressed digestにすることが想定されるが、参照形式、sourceのcanonicalization、digest algorithmはTransport Bindingで定義する。
|
|
||||||
|
|
||||||
## Interface exchange
|
|
||||||
|
|
||||||
HostはInterfaceについて、少なくとも次をClientへ提供する。
|
|
||||||
|
|
||||||
| 項目 | 内容 |
|
|
||||||
| --- | --- |
|
|
||||||
| Interface reference | Objectが保持し、`fetch_interface`の対象となる参照 |
|
|
||||||
| Language identifier | 初期versionは`wip-idl/1` |
|
|
||||||
| Source | WIP IDL source |
|
|
||||||
| Digest | Cacheと同一性確認に利用するdigest |
|
|
||||||
|
|
||||||
交換されるInterface定義の正本はWIP IDL sourceである。HostはJSON SchemaやIDL ASTを併記する必要はない。
|
|
||||||
|
|
||||||
ClientはIDLを内部ASTへparseし、必要に応じてAI provider用JSON Schema、GUI form、言語固有の型などを生成できる。
|
|
||||||
|
|
||||||
ClientはObjectのInterface参照をcacheと比較し、未知のInterfaceだけを`fetch_interface`する。複数のInterface取得はTransport Bindingでbatchできる。HostはClientのcache状態を推測せず、ObjectのresponseへInterface定義を先行同梱しない。
|
|
||||||
|
|
||||||
## 未解決事項
|
|
||||||
|
|
||||||
- Sourceのcanonicalizationとdigestの厳密な計算方法。
|
|
||||||
- Interface参照の具体的な形式とscope。
|
|
||||||
- String length、numeric range、pattern等のconstraintを導入するか。
|
|
||||||
- Recursive named typeを許可するか。
|
|
||||||
- `i64`、`u64`、`bigint`、`decimal`等を追加するか。
|
|
||||||
- `entry`が参照するpathのcanonicalization規則。
|
|
||||||
+232
-47
@@ -1,49 +1,165 @@
|
|||||||
# WIP over HTTPS
|
# WIP over HTTPS
|
||||||
|
|
||||||
WIP over HTTPSは、**WIP Core ProtocolをHTTPS上へ対応付ける標準Transport Binding**である。
|
WIP over HTTPSは、[WIP Protocol](../3-protocol.md)のlogical data modelをHTTPS上へ対応付ける標準Transport Bindingである。
|
||||||
|
|
||||||
## 目的
|
## 目的
|
||||||
|
|
||||||
Core Protocolの意味論を変えずに、既存のWebインフラを利用してClientとHostを接続する。
|
Protocolの意味論を変えずに、既存のWeb infrastructureを利用してClientとHostを接続する。
|
||||||
|
|
||||||
## 方針
|
## 方針
|
||||||
|
|
||||||
初期の標準bindingはHTTPS上のrequest / responseのみを規定する。TLS、認証、Proxy、Gateway、Observability、Caching、connection reuse、multiplexing、compression等の既存機構を利用してよいが、特定のHTTP versionや実装方式を必須にしない。
|
初期の標準bindingはHTTPS上のrequest / responseのみを規定する。TLS、認証、Proxy、Gateway、Observability、Caching、connection reuse、multiplexing、compression等の既存機構を利用してよいが、特定のHTTP versionや実装方式を必須にしない。
|
||||||
|
|
||||||
OperationがWebSocket等のendpointを通常のdomain valueとして返すことは妨げない。そのendpoint上のprotocol、状態、lifecycleはWIPの規定対象外であり、ClientとHost固有実装の責務とする。
|
OperationがWebSocket等のendpointを通常のApplication dataとして返すことは妨げない。そのendpoint上のprotocol、状態、lifecycleはWIPの規定対象外であり、ClientとHost固有実装の責務とする。
|
||||||
|
|
||||||
双方向socket transportをWIP bindingとして標準化する場合は、将来の独立した拡張として定義する。
|
双方向socket transportをWIP bindingとして標準化する場合は、将来の独立した拡張として定義する。
|
||||||
|
|
||||||
## Binding対象
|
## Binding対象
|
||||||
|
|
||||||
少なくとも、Core Protocolの以下の操作をHTTP request / responseへ対応付ける。
|
少なくとも、Protocolの以下のinteractionをHTTP request / responseへ対応付ける。
|
||||||
|
|
||||||
- `fetch`
|
- `fetch`
|
||||||
- `fetch_tree`
|
- `fetch_tree`
|
||||||
- `fetch_interface`
|
- `fetch_interface`
|
||||||
- `call_operation`
|
- `call_operation`
|
||||||
|
|
||||||
具体的なHTTP method、endpoint、content type、error mapping、認証方式、batch表現などは、このbinding仕様側で定義する。
|
具体的なHTTP method、endpoint、content type、error mapping、認証方式、validator mapping、batch表現は、このbinding仕様側で定義する。
|
||||||
|
|
||||||
## Interfaceの取得
|
## JSON encodingの基本規則
|
||||||
|
|
||||||
Objectの公開情報はOperation定義を直接含まず、[WIP IDL](wip-idl.md) documentで定義されたInterfaceへの参照を持つ。`fetch_interface`は、その参照に対応するInterfaceのlanguage identifier、source、digestを返す。
|
ProtocolのrecordはJSON object、listはJSON array、optional fieldの省略はJSON fieldの省略としてencodeする。
|
||||||
|
|
||||||
HTTPS response全体をJSON envelopeにする場合、IDL sourceをJSON stringとして格納してよい。ただし、これはIDLをJSON ASTへ変換するものではない。BindingはIDL sourceを専用resourceおよびcontent typeで直接取得する方法を定義してもよい。
|
Protocol structの`String`はJSON string、`Vec<u8>`はbindingが定めるopaque encodingへ対応付ける。Path、Interface参照、Object identity、名前等の意味はJSON typeではなくfieldの位置によって決まる。
|
||||||
|
|
||||||
ClientはObjectのInterface参照をcacheと比較し、未知のInterfaceだけを`fetch_interface`する。HostはClientのcache状態を推測せず、`fetch`や`fetch_tree`のresponseへInterface定義を先行同梱しない。複数のInterface取得はHTTP batchingでまとめられる。
|
| Field | JSON encoding | 解釈 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `path` | string | canonical absolute Worldspace path |
|
||||||
|
| `name`、Operation / Type / Field / Parameter / Case名 | string | 各struct内の名前 |
|
||||||
|
| `interface` | string | Interface Descriptorへの参照 |
|
||||||
|
| `format` | string | Descriptor format identifier |
|
||||||
|
| `ref` | string | opaqueなObject identity |
|
||||||
|
| `validator` | base64 stringまたはHTTP metadata | opaqueな条件付き操作用value |
|
||||||
|
|
||||||
## Operation valueのJSON encoding
|
Validatorをresponse bodyのbase64 stringとして運ぶか、HTTP ETag等へ対応付けるかは、このbindingがresponse形態ごとに定める。どちらの場合もClient runtimeは値をopaqueに扱い、AIやユーザーへ直接管理させない。
|
||||||
|
|
||||||
WIP over HTTPSでは、`call_operation`のargumentsとresultを、選択したOperation declarationに従うJSON valueとしてencodeする。JSONはHTTPS binding上の値表現であり、WIP CoreのInterface定義形式ではない。
|
未知のJSON fieldを許可する箇所はProtocol側で明示する。Object、Interface Descriptor、request / response、Protocol errorの未宣言fieldは既定で拒否する。
|
||||||
|
|
||||||
`arguments`はOperationのparameter名をfield名とするJSON objectとする。位置引数は用いず、引数を持たないOperationには空のobjectを渡す。
|
## Objectの取得
|
||||||
|
|
||||||
|
`fetch` requestはpathとして解釈されるstringを`path`に渡し、Objectを直接受け取る。
|
||||||
|
|
||||||
概念的なrequest bodyは次の形になる。
|
概念的なrequest bodyは次の形になる。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"target": "/items/current",
|
"path": "/items/123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Responseは次の形になる。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "123",
|
||||||
|
"description": "First item",
|
||||||
|
"interface": "item-interface-v1",
|
||||||
|
"ref": "item:123",
|
||||||
|
"validator": "b3BhcXVlLXZhbGlkYXRvcg=="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ref`、`description`、`validator`はoptional fieldであり、存在しない場合はfield自体を省略する。JSON `null`を代わりに使用しない。
|
||||||
|
|
||||||
|
Request pathはresponseへ重複して含めない。HTTP batchを使用する場合も、subrequestの`id`によってrequest pathとObject responseを対応付ける。
|
||||||
|
|
||||||
|
## Treeの取得
|
||||||
|
|
||||||
|
`fetch_tree` requestは起点path、depth、limitを渡す。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"path": "/items",
|
||||||
|
"depth": 1,
|
||||||
|
"limit": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Responseは各nodeのObjectとchildrenを含む。各Objectのpathはrequest pathとObjectの`name`から導出し、validatorはObjectのfieldとしてencodeする。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"root": {
|
||||||
|
"object": {
|
||||||
|
"name": "items",
|
||||||
|
"description": "Item collection",
|
||||||
|
"interface": "sha256:item-collection-interface",
|
||||||
|
"validator": "cm9vdC12YWxpZGF0b3I="
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"object": {
|
||||||
|
"name": "123",
|
||||||
|
"description": "First item",
|
||||||
|
"interface": "item-interface-v1",
|
||||||
|
"ref": "item:123",
|
||||||
|
"validator": "aXRlbS12YWxpZGF0b3I="
|
||||||
|
},
|
||||||
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"truncated": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`depth`または`limit`によって存在するindexable childを省略した場合、`truncated`を`true`にする。
|
||||||
|
|
||||||
|
## Interfaceの取得
|
||||||
|
|
||||||
|
ObjectはOperation定義を直接含まず、Interface Descriptorへの参照を持つ。`fetch_interface`は、その参照に対応するDescriptorを返す。
|
||||||
|
|
||||||
|
Conceptual requestは次の形になる。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"interface": "item-interface-v1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Responseは次の形になる。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"interface": "item-interface-v1",
|
||||||
|
"descriptor": {
|
||||||
|
"format": "wip-interface/1",
|
||||||
|
"documentation": {
|
||||||
|
"summary": "Operations provided by an item."
|
||||||
|
},
|
||||||
|
"types": [],
|
||||||
|
"operations": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Interface DescriptorはJSON-compatibleなlogical structとしてProtocolで定義される。JSONはHTTPS上のencodingであり、Interface実装者が手書きするauthoring形式ではない。
|
||||||
|
|
||||||
|
ClientはObjectのInterface参照をcacheと比較し、未知のDescriptorだけを`fetch_interface`する。HostはClientのcache状態を推測せず、`fetch`や`fetch_tree`のresponseへDescriptorを先行同梱しない。複数のInterface取得はHTTP batchingでまとめられる。
|
||||||
|
|
||||||
|
## Operation valueのJSON encoding
|
||||||
|
|
||||||
|
`call_operation`のargumentsとresultは、選択したOperation declarationに従うJSON valueとしてencodeする。
|
||||||
|
|
||||||
|
`arguments`はOperationのparameter名をfield名とするJSON objectとする。位置引数は用いず、引数を持たないOperationには空のobjectを渡す。
|
||||||
|
|
||||||
|
Conceptual request bodyは次の形になる。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"target": {
|
||||||
|
"path": "/items/current",
|
||||||
|
"validator": "b3BhcXVlLXZhbGlkYXRvcg=="
|
||||||
|
},
|
||||||
"operation": "get_related_item",
|
"operation": "get_related_item",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"relation": "sibling",
|
"relation": "sibling",
|
||||||
@@ -52,22 +168,101 @@ WIP over HTTPSでは、`call_operation`のargumentsとresultを、選択したOp
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
IDL型からJSONへのmappingはbindingで一意に定める。少なくとも次の規則を持つ。
|
ResponseはOperation resultと、実行後の現在状態に対してHostが発行したoptionalなvalidatorを返す。
|
||||||
|
|
||||||
- `boolean`、`string`、`number`、record、listは対応するJSON valueで表す。
|
```json
|
||||||
- optionalなparameterまたはrecord fieldはfieldの省略で表し、`null`とは区別する。
|
{
|
||||||
- unit形式のenumはstring、payloadを持つunionは明示的なdiscriminatorを持つobjectで表す。
|
"result": {
|
||||||
- `bytes`はbase64でencodeしたstringとして表す。
|
"item": "/items/123"
|
||||||
- 通常のJSON numberで表す`integer`は相互運用可能な安全範囲に制限する。それを超える整数型を設ける場合はdecimal string等のlosslessな表現を定義する。
|
},
|
||||||
- WIP IDLの`entry`は、同じWorldspace内のcanonical absolute pathをJSON stringとして表す。
|
"validator": "bmV3LXZhbGlkYXRvcg=="
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
ClientはWIP IDLに従ってvalueをdecodeし、IDL上で`entry`と宣言された位置にある文字列だけをエントリとして認識する。通常の`string`や任意JSON値に含まれるpathらしい文字列を、エントリとして推測してはならない。
|
RawなProtocol ValueからJSONへのmappingはbindingで一意に定める。
|
||||||
|
|
||||||
|
| Protocol value | JSON encoding |
|
||||||
|
| --- | --- |
|
||||||
|
| `Unit` | `null` |
|
||||||
|
| `Boolean` | boolean |
|
||||||
|
| `Integer` | safe integer範囲のnumber |
|
||||||
|
| `Number` | finiteなnumber |
|
||||||
|
| `String` | string |
|
||||||
|
| `Bytes` | RFC 4648 Section 4のbase64 string |
|
||||||
|
| `Record` | object |
|
||||||
|
| `List` | array |
|
||||||
|
|
||||||
|
`Entry`、Enum、Union、`Json`はraw Valueのvariantではなく、Interface Descriptorがprimitiveおよびcompositeへ与える解釈である。
|
||||||
|
|
||||||
|
| TypeExpr | JSON encoding |
|
||||||
|
| --- | --- |
|
||||||
|
| `Entry` | canonical absolute pathのstring |
|
||||||
|
| Enum | case名のstring |
|
||||||
|
| Union | `$case`とoptionalな`value`を持つobject |
|
||||||
|
| `Json` | 任意のJSON value。ただし`Bytes`を含まない |
|
||||||
|
|
||||||
|
Optionalなparameterまたはrecord fieldはfieldの省略で表し、`null`とは区別する。
|
||||||
|
|
||||||
|
Payloadを持つUnionは次のようにencodeする。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$case": "found",
|
||||||
|
"value": "/items/123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Payloadを持たないUnionは`value`を省略する。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$case": "not_found"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
ClientはInterface Descriptorに従ってvalueをdecodeし、`entry`と宣言された位置にあるstringだけをエントリとして認識する。通常の`string`やopaqueな`json`に含まれるpathらしいstringをエントリとして推測してはならない。
|
||||||
|
|
||||||
|
## ValidatorとHTTP conditional request
|
||||||
|
|
||||||
|
WIP Protocolのlogical fieldは、ObjectおよびOperation responseの`validator`と、Operation requestの`target.validator`である。
|
||||||
|
|
||||||
|
単独のHTTP request / responseで、WIP validatorがHTTPのstrong validator semanticsを満たす場合、HTTPS Bindingは次へ対応付けてよい。
|
||||||
|
|
||||||
|
```text
|
||||||
|
Object.validatorまたはCallOperationResponse.validator -> ETag
|
||||||
|
CallOperationRequest.target.validator -> If-Match
|
||||||
|
validator_mismatch -> 412 Precondition Failed
|
||||||
|
validator_required -> 428 Precondition Required
|
||||||
|
```
|
||||||
|
|
||||||
|
HTTP headerへmappingした場合も、Client adapterはProtocol上のObjectまたはresponseへvalidatorを復元する。ValidatorがHTTP response representationの変更を反映しない場合、strong ETagとして使用してはならず、body fieldで運ぶ。
|
||||||
|
|
||||||
|
Batchではsubresponseごとにvalidatorが存在し得るため、各ObjectまたはOperation responseのbody fieldとしてencodeする。
|
||||||
|
|
||||||
|
## Protocol error
|
||||||
|
|
||||||
|
Protocol failureをJSON response bodyへ含める場合、概念的に次の形を使用する。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": {
|
||||||
|
"code": "invalid_arguments",
|
||||||
|
"message": "Required argument `relation` is missing"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`code`はProtocolが定義する安定した識別子、`message`は人間向けのboundedな診断である。Clientは`message`の内容で分岐しない。
|
||||||
|
|
||||||
|
Protocol error codeとHTTP statusのmapping、認証情報を漏らさないための`not_found`と`permission_denied`の使い分け、validation errorのstructured detailは未確定である。
|
||||||
|
|
||||||
|
Domain failureをProtocol errorへ変換しない。Domain failureはOperation resultのApplication dataとしてencodeする。
|
||||||
|
|
||||||
## HTTP batching
|
## HTTP batching
|
||||||
|
|
||||||
WIP over HTTPSは、複数の独立したCore取得requestを一つのHTTP requestへまとめるbatch形式を提供する。Batchingは通信上のpackagingであり、Core Protocolへ新しい操作や意味論を追加しない。
|
WIP over HTTPSは、複数の独立したCore取得requestを一つのHTTP requestへまとめるbatch形式を提供する。Batchingは通信上のpackagingであり、Protocolへ新しいinteractionや意味論を追加しない。
|
||||||
|
|
||||||
Clientは、Known SpaceとInterface cacheをもとに必要なrequestだけを選択してbatchを構成する。HostはClientの既知状態を推測して、要求されていないentry公開情報やInterface定義をresponseへ追加しない。
|
ClientはKnown SpaceとInterface cacheをもとに必要なrequestだけを選択してbatchを構成する。HostはClientの既知状態を推測して、要求されていないObjectやInterface Descriptorをresponseへ追加しない。
|
||||||
|
|
||||||
Batch endpointは概念的に`POST {wip-endpoint}/batch`とし、bodyに一意な`id`を持つsubrequestの配列を格納する。
|
Batch endpointは概念的に`POST {wip-endpoint}/batch`とし、bodyに一意な`id`を持つsubrequestの配列を格納する。
|
||||||
|
|
||||||
@@ -78,21 +273,14 @@ Batch endpointは概念的に`POST {wip-endpoint}/batch`とし、bodyに一意
|
|||||||
"id": "entry-123",
|
"id": "entry-123",
|
||||||
"method": "fetch",
|
"method": "fetch",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"entry": "/items/123"
|
"path": "/items/123"
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "entry-456",
|
|
||||||
"method": "fetch",
|
|
||||||
"arguments": {
|
|
||||||
"entry": "/items/456"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "item-interface",
|
"id": "item-interface",
|
||||||
"method": "fetch_interface",
|
"method": "fetch_interface",
|
||||||
"arguments": {
|
"arguments": {
|
||||||
"interface": "sha256:item-interface"
|
"interface": "item-interface-v1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -109,23 +297,20 @@ Hostは各subrequestを、単独で受け取った場合と同じ規則で処理
|
|||||||
"result": {
|
"result": {
|
||||||
"name": "123",
|
"name": "123",
|
||||||
"description": "First item",
|
"description": "First item",
|
||||||
"interface": "sha256:item-interface"
|
"interface": "item-interface-v1",
|
||||||
}
|
"ref": "item:123",
|
||||||
},
|
"validator": "b3BhcXVlLXZhbGlkYXRvcg=="
|
||||||
{
|
|
||||||
"id": "entry-456",
|
|
||||||
"error": {
|
|
||||||
"code": "not_found",
|
|
||||||
"message": "Entry not found"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "item-interface",
|
"id": "item-interface",
|
||||||
"result": {
|
"result": {
|
||||||
"interface": "sha256:item-interface",
|
"interface": "item-interface-v1",
|
||||||
"language": "wip-idl/1",
|
"descriptor": {
|
||||||
"digest": "sha256:item-interface",
|
"format": "wip-interface/1",
|
||||||
"source": "..."
|
"types": [],
|
||||||
|
"operations": []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -140,14 +325,14 @@ Batchには次の規則を適用する。
|
|||||||
- Batch全体はtransactionではなく、atomicity、共通snapshot、実行順序を保証しない。
|
- Batch全体はtransactionではなく、atomicity、共通snapshot、実行順序を保証しない。
|
||||||
- Hostはsubrequestを直列または並列に実行してよい。
|
- Hostはsubrequestを直列または並列に実行してよい。
|
||||||
- Subrequest間で、先行requestのresultを後続requestのargumentsとして参照できない。
|
- Subrequest間で、先行requestのresultを後続requestのargumentsとして参照できない。
|
||||||
- 各`result`は対応するCore操作を単独で呼んだ場合と同じvalueとする。
|
- 各`result`は対応するProtocol interactionを単独で呼んだ場合と同じvalueとする。
|
||||||
- 各`error`は通常のProtocol errorと同じschemaを使用する。
|
- 各`error`は通常のProtocol errorと同じschemaを使用する。
|
||||||
- HostはClientが要求していないsubresponseを追加してはならない。
|
- HostはClientが要求していないsubresponseを追加してはならない。
|
||||||
|
|
||||||
初期のbatch形式に格納できるのは`fetch`、`fetch_tree`、`fetch_interface`とし、`call_operation`は含めない。将来、WIP IDLのEffect annotationを採用する場合に、副作用を持たないと明示されたOperationをbatch対象へ加えるかを改めて検討する。
|
初期のbatch形式に格納できるのは`fetch`、`fetch_tree`、`fetch_interface`とし、`call_operation`は含めない。将来Effect annotationを採用する場合に、副作用を持たないと明示されたOperationをbatch対象へ加えるかを改めて検討する。
|
||||||
|
|
||||||
Batch件数、request / response byte size、timeoutの上限、およびbatch envelope自体が不正な場合のHTTP statusはbindingの詳細として定める。
|
Batch件数、request / response byte size、timeoutの上限、およびbatch envelope自体が不正な場合のHTTP statusはbindingの詳細として定める。
|
||||||
|
|
||||||
## 非目標
|
## 非目標
|
||||||
|
|
||||||
WIP over HTTPSはHost内部のAPIやデータソース接続方式を規定しない。また、WIP Core ProtocolそのものをHTTP依存のモデルへ変えることも目的としない。
|
WIP over HTTPSはHost内部のAPIやdata source接続方式を規定しない。また、WIP ProtocolそのものをHTTP依存のmodelへ変えることも目的としない。
|
||||||
|
|||||||
Reference in New Issue
Block a user