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
+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を失ってはならない。