# 5.1. WIP over HTTP WIP over HTTPは、[3. Protocol](3-protocol.md)のlogical data modelをHTTP request / responseとJSONへ対応付ける標準Transport Bindingである。HTTP上の表現は、[5. Transport Bindings](5-transports.md)の共通要件に従って定める。 ## 目的と範囲 HTTPへ対応付けるCore interactionは、次の三つである。 - `observe` - `fetch_interface` - `call_operation` HTTP version、communication scheme、TLS、authentication方式、connection reuse、multiplexing、proxy、gateway、cache、Host内部のframework、backend接続方式は規定しない。これらはHTTP実装とdeploymentが、WIPとは独立して選択する。複数のCore interactionが必要な場合も、それぞれを独立したHTTP request / responseとして交換する。 Operationは、WebSocket等のendpointをApplication dataとして返してよい。ただし、そのendpoint上のprotocol、状態、lifecycleは、WIPの規定対象外である。 ## Endpoint WIP endpointは、一つのWorldspace access surfaceを指すabsolute hierarchical base URLである。URLのpath prefixはdeploymentが任意に選択できる。Clientはorigin直下や`/wip`等の既定prefixを仮定せず、Worldspace pathとの対応も仮定しない。 Endpoint URLには、次の条件を適用する。 - HTTP実装がrequest先として使用できるabsolute URLである。 - Authorityとhostを持つ。 - Queryとfragmentを持たない。 - Pathが`/`で終わるcanonical formである。 利用者から末尾`/`のないURLを受け付ける実装は、routeを解決する前に`/`を追加し、canonical formへ変換する。URL schemeと通信securityはHTTP実装とdeploymentが選択し、このbindingは制約しない。 各routeは、endpoint URLをbase URLとして、次のrelative referenceをRFC 3986に従って解決する。すべてのinteractionで`POST`を使用する。 | Interaction | Method | Relative reference | | --- | --- | --- | | `observe` | `POST` | `v1/observe` | | `fetch_interface` | `POST` | `v1/fetch_interface` | | `call_operation` | `POST` | `v1/call_operation` | `v1`は、WIP over HTTP Bindingのmajor versionを表す。Interactionごとに独立したrouteを設定したり、固定suffixを別名へ置き換えたりしない。 例えば、endpointが次のURLである場合、 ```text http://gateway.example/tenants/acme/filesystem/wip/ ``` `observe` routeは次のURLになる。 ```text http://gateway.example/tenants/acme/filesystem/wip/v1/observe ``` このpath prefixはHTTP deployment上のroutingであり、Worldspace内のpathではない。Worldspace pathは、request bodyのlogical fieldとして渡す。標準route URLはqueryを持たず、query付きURLや追加path segmentを同じrouteとして扱わない。 Clientは、異なるcanonical endpoint間でKnown Space、Object observation、Interface observation、validatorを混在させない。同じendpointでも、認証主体、tenant、capability、その他のsecurity contextによって異なるWorldspaceが見える場合は、異なるeffective Worldspace viewとして分離する。 ## HTTP request metadata 標準routeへのrequestには、次の条件を適用する。 - Methodは`POST`。 - `Content-Type`は`application/json`または`application/json; charset=utf-8`。 - BodyはUTF-8のJSON text。 - 標準Clientは`Accept: application/json`を送る。 - Request URLは標準routeと完全に一致し、queryを持たない。 Media typeとparameter名は、HTTPの規則に従ってcase-insensitiveに比較する。`charset`を指定する場合に許可するのは`utf-8`だけである。同じparameterの重複、UTF-8以外のcharset、その他のmedia type parameterは、標準bindingでは使用しない。 Hostは、`Accept`がないrequestを受理してよい。`Accept`がある場合はHTTP content negotiationの規則を適用し、`application/json`に対するeffective quality valueが正である場合だけ、JSON responseを返す。 すべての実装はHTTP identity content codingを扱える。Requestとresponseのcontent codingはoptionalなHTTP機能であり、このbindingは特定の圧縮方式を必須にしない。Hostが対応しないrequest content codingは、Transport-levelの`415 Unsupported Media Type`として拒否する。Clientが対応しないresponse content codingは、Transport failureとして扱う。 ## Routeとmetadataのfailure Route、method、content negotiation、Transport authenticationは、logical WIP requestの外側で扱う。次のresponseには、Protocol error envelopeを要求しない。 | 条件 | HTTP response | | --- | --- | | 未知route、query付きroute、追加path segment | `404 Not Found` | | 既知routeへの`POST`以外のmethod | `405 Method Not Allowed`と`Allow: POST` | | Unsupportedな`Content-Type`またはrequest content coding | `415 Unsupported Media Type` | | JSON responseを拒否する`Accept` | `406 Not Acceptable` | | Transport authenticationが必要 | `401 Unauthorized`、必要なら`WWW-Authenticate` | | Endpoint access surface全体へのaccess拒否 | `403 Forbidden` | Clientは、これらを`InvalidRequest`、`NotFound`、`PermissionDenied`等へ変換しない。 一方、標準route、method、media type、authenticationを受理した後に、bodyがmalformed JSONである、logical requestへdecodeできない、required fieldがない、未知fieldがある、またはfield semanticsに違反する場合は、Protocol failureとなる。Hostは`400 Bad Request`と、`invalid_request`のProtocol error envelopeを返す。 HTTP server、proxy、gateway、Clientの運用設定によってmessage size、timeout、rate等の上限に達した場合は、Transport failureである。HTTP statusがProtocol error mappingと同じでも、validなProtocol error envelopeを持たないresponseをProtocol failureへ変換しない。 ## HTTP response 各interactionが成功した場合、Hostは`200 OK`を返す。Response bodyには、対応するProtocol responseを直接encodeし、`result`等の共通envelopeで包まない。 Protocol failureの場合は非2xx statusを返し、bodyにProtocol error envelopeをencodeする。 WIP Hostが生成するbody付きresponseは、`Content-Type: application/json`または`application/json; charset=utf-8`を持つ。Protocol successとProtocol failureのbodyは、いずれもUTF-8 JSON textである。 HTTP statusは、大分類とHTTP infrastructureのための補助情報である。Protocol failureの意味を決定するものではなく、Clientはstatus、reason phrase、人間向けmessageから`ProtocolErrorCode`を推測しない。 非2xx responseが、正しいContent-TypeとvalidなProtocol error envelopeを持たない場合、ClientはTransport failureとして扱う。Proxyやgatewayが生成したresponseを、Host由来のProtocol failureと誤認しないためである。 これに対し、次のresponseは`InvalidResponse`となる。 - `200 OK`以外の2xx statusにvalidなsuccess bodyがある。 - 2xx statusにProtocol error envelopeがある。 - 非2xx statusにvalidなsuccess bodyがある。 - Success bodyまたはProtocol error envelopeがschema、request correlation、interactionごとのcode制約に違反する。 ## JSON共通規則 JSON encodingには、次の規則を適用する。 - JSON textはUTF-8でencodeする。 - RecordはJSON object、listはJSON arrayで表す。 - Field名と列挙stringはcase-sensitiveである。 - 同じJSON object内のduplicate memberを拒否する。 - 本章がschemaを定義するobjectでは、許可していないmemberを拒否する。Descriptorの未知formatとTypeExpr `Json`のobjectには、それぞれ後述する例外を適用する。 - Required fieldは必ず存在する。 - Protocol structのoptional fieldはmemberの省略で表し、`null`で置き換えない。 - JSON objectのmember順に意味を持たせない。 - Protocol listのarray順は保持する。 - StringへUnicode normalizationを適用しない。 - JSON syntaxが表現できないNaNと正負Infinityを使用しない。 Schema表で`optional`と記していないfieldは、requiredとして扱う。 `Vec`はcanonical base64 stringとしてencodeする。RFC 4648 Section 4のstandard base64 alphabetを使用し、必要な`=` paddingを含める。Whitespace、URL-safe alphabet、padding省略、同じoctet列に対する別表現は受理しない。 Path、Interface参照、Object identity、名前、validatorの意味は、fieldの位置とProtocolの型によって決まる。JSON上の表現は次のとおりである。 | Logical field | JSON encoding | | --- | --- | | Path / `entry` | canonical absolute Worldspace pathのstring | | Object、Operation、Type、Field、Parameter、Case名 | string | | Interface参照 | `InterfaceReference` object | | `ref` | string | | `format` | string | | Object / Interface validator | canonical base64 string | ただし、JSON serialization全体をcanonical化するわけではない。Whitespace、escapeの選択、object member順はcanonical化せず、同じlogical valueがbyte-for-byte同一のJSONになることも要求しない。 ## Interface Reference `InterfaceReference`は、次のfieldだけを持つexactなJSON objectとしてencodeする。 | Field | JSON type | Presence | | --- | --- | --- | | `scope` | canonical absolute Worldspace pathのstring | required | | `name` | 空でないUnicode string | required | ```json { "scope": "/github", "name": "issue.read" } ``` `Object.interfaces`の各要素、`FetchInterfaceRequest.interface`、`FetchInterfaceResponse.interface`、`InterfaceTarget.reference`で、この形を共通して使用する。Scopeの省略、relative scope、`null`、空name、追加member、旧形式のopaque string、`"/github::issue.read"`等の短縮表記stringは認めない。Requestで違反した場合は`400 Bad Request`と`invalid_request`を返し、responseで違反した場合はClient-localな`InvalidResponse`とする。 参照は、JSON decode後の`scope`と`name`の完全一致で比較する。Object member順やJSON escapeの違いは、同一性に影響しない。ScopeへURL encoding / decodingを追加せず、name内の`::`や`#`も通常の文字として保持する。 ScopeはWorldspace上のpathである。HTTP endpointのprefixを加えたり、scope用のHTTP routeを生成したりしない。合成によるscope変換は、[ProtocolのWorldspace composition](3-protocol.md#worldspace-composition)に従う。 ## ObjectとObjectObservation `Object`は、次のfieldを持つJSON objectとしてencodeする。 | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `description` | string | optional | | `interfaces` | `InterfaceReference` objectのarray | required | | `ref` | string | optional | | `validator` | canonical base64 string | optional | ObjectのJSON表現の例: ```json { "name": "123", "description": "First item", "interfaces": [ { "scope": "/", "name": "item-interface-v1" }, { "scope": "/", "name": "item-marker-interface-v1" } ], "ref": "item:123", "validator": "aXRlbS12YWxpZGF0b3I=" } ``` `interfaces`のarray順にはHostの立項順を保持し、`(scope, name)`の完全一致による重複を含めない。各参照のscopeは、観測pathに対してProtocolの祖先制約を満たす。 `ObjectObservation`は、Objectとchildrenの観測を次のJSON objectで表す。 | Field | JSON type | Presence | | --- | --- | --- | | `object` | `Object` | required | | `children` | `ObjectObservation`のarray | optional | `children`の省略は未観測を表す。空arrayは、観測済みで直接のindexable childが存在しないことを表す。Requested depthより浅いnodeでは`children`を必ず含め、depth境界のnodeでは省略する。 Success responseはrequested depthまで完全であり、truncated markerやpartial successを返さない。 ## Interface Descriptor ### Format discriminator 標準v1のInterface Descriptor formatは、`wip-interface/1`である。このformatのJSON grammarは、以下の定義に従う。 Clientは、Descriptor objectのstring `format`を先に読み、対応しないformatを`UnsupportedDescriptorFormat`として扱える。未知formatでも、DescriptorはJSON objectであり、string `format`を必ず持つ。 それ以外のmemberはformat固有であるため、未知formatを`wip-interface/1`のschemaで検証しない。Memberの存在、欠落、型をこのschemaで判定せず、内容をOperationへ使用しない。標準v1 Hostは`wip-interface/1`を返す。 ### Documentation `Documentation`は、説明を次のJSON objectで表す。 | Field | JSON type | Presence | | --- | --- | --- | | `summary` | string | required | | `details` | string | optional | ### Descriptor root `InterfaceDescriptor`のrootは、次のJSON objectである。 | Field | JSON type | Presence | | --- | --- | --- | | `format` | string。標準v1では`wip-interface/1` | required | | `documentation` | `Documentation` | optional | | `types` | `TypeDeclaration`のarray | required | | `operations` | `OperationDeclaration`のarray | required | `types`と`operations`のarrayには、declaration順を保持する。 ### TypeDeclaration | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `documentation` | `Documentation` | optional | | `definition` | `TypeExpr` | required | ### TypeExpr すべての`TypeExpr`を、string `kind`を持つJSON objectとしてencodeする。`kind`ごとに持つmemberは、次のものに限定する。 | TypeExpr | `kind` | その他のmember | | --- | --- | --- | | Unit | `unit` | なし | | Boolean | `boolean` | なし | | Integer | `integer` | なし | | Number | `number` | なし | | String | `string` | なし | | Bytes | `bytes` | なし | | Json | `json` | なし | | Entry | `entry` | なし | | Named | `named` | required string `name` | | Record | `record` | required `FieldDeclaration` array `fields` | | List | `list` | required `TypeExpr` `items` | | Enum | `enum` | required `EnumCase` array `cases` | | Union | `union` | required `UnionCase` array `cases` | ListのitemsがNamedであるTypeExprの例: ```json { "kind": "list", "items": { "kind": "named", "name": "ItemSummary" } } ``` Primitive kindのobjectに、別memberを追加してはならない。例えばUnitの表現は、`{"kind":"unit"}`だけである。 ### FieldDeclaration | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `required` | boolean | required | | `documentation` | `Documentation` | optional | | `type` | `TypeExpr` | required | ### EnumCase | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `documentation` | `Documentation` | optional | ### UnionCase | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `documentation` | `Documentation` | optional | | `payload` | `TypeExpr` | optional | `payload`を省略したcaseは、payloadを持たない。 ### OperationDeclaration | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `documentation` | `Documentation` | optional | | `parameters` | `ParameterDeclaration`のarray | required | | `returns` | `ReturnDeclaration` | required | ### ParameterDeclaration | Field | JSON type | Presence | | --- | --- | --- | | `name` | string | required | | `required` | boolean | required | | `documentation` | `Documentation` | optional | | `type` | `TypeExpr` | required | ### ReturnDeclaration | Field | JSON type | Presence | | --- | --- | --- | | `documentation` | `Documentation` | optional | | `type` | `TypeExpr` | required | JSON shapeの検証だけでは、Descriptorのvalidityは確認できない。名前一意性、Named参照、cycle、型整合性等も、[3. Protocol](3-protocol.md)に従って検証する。 Typesとoperationsを含む、完全なDescriptorの例: ```json { "format": "wip-interface/1", "documentation": { "summary": "Reads items and their relationships." }, "types": [ { "name": "Relation", "definition": { "kind": "enum", "cases": [ { "name": "parent" }, { "name": "sibling" } ] } }, { "name": "RelatedItem", "definition": { "kind": "union", "cases": [ { "name": "found", "payload": { "kind": "entry" } }, { "name": "not_found" } ] } } ], "operations": [ { "name": "get_related_item", "parameters": [ { "name": "relation", "required": true, "type": { "kind": "named", "name": "Relation" } } ], "returns": { "type": { "kind": "named", "name": "RelatedItem" } } } ] } ``` ## Operation Value Operationのargumentsとresultは、選択したInterface Descriptorの`TypeExpr`に従ってJSONへencodeする。Raw `Value` variantを示す共通tagged envelopeは使用しない。 | TypeExpr | JSON encoding | | --- | --- | | Unit | `null` | | Boolean | boolean | | Integer | 小数部と指数部を持たないJSON number。`-9007199254740991`から`9007199254740991`まで | | Number | finiteなJSON number | | String | string | | Bytes | canonical base64 string | | Json | JSONの`null`、boolean、number、string、array、object | | Entry | canonical absolute Worldspace pathのstring | | Named | 同じDescriptor内の参照先TypeExprと同じencoding | | Record | declarationされたfieldをmemberとするobject | | List | items TypeExprに従うarray | | Enum | 宣言されたcase名のstring | | Union | `$case`と、必要なら`value`を持つobject | `Json`内部のnumberにも、相互運用可能なsafe integerまたはfinite binary64という制約を適用する。小数部と指数部を持たずsafe integer範囲にあるJSON numberはlogical `Integer`として、それ以外のfiniteなJSON numberはlogical `Number`としてdecodeする。 `Json`内部にはBytesの特別なencodingを適用しない。Base64らしいstringがあっても、Bytesと推測しない。 RecordとOperation argumentsでは、`required = false`のfieldやparameterを省略できる。ただし、省略と`null`は異なる。TypeExprがUnit、Json、またはそれらへ解決されるNamedである場合、存在するmemberの`null`はその型のvalueであり、省略を表さない。それ以外の型では`null`を使用してはならない。 Record valueには、declarationされていないmemberを含めない。Operation argumentsは、parameter名をmember名とするJSON objectであり、位置引数を使用しない。引数のないOperationには空objectを使用する。 Enumはcase名だけをstringで表し、object envelopeは使用しない。 Payloadを持つUnionは、`$case`と`value`を持つ次の形で表す。 ```json { "$case": "found", "value": "/items/123" } ``` Payloadを持たないUnionでは、`value`を省略する。 ```json { "$case": "not_found" } ``` Union objectに含めるmemberは、`$case`と必要な`value`だけである。Payloadありcaseでは`value`がrequiredとなり、payloadなしcaseでは`value`を禁止する。 Clientは、Descriptorに従ってvalueをdecodeする。Worldspace entryとして認識するのは、`entry`と宣言された位置のstringだけである。通常のStringやopaqueなJsonに含まれるpathらしいstringから、entryを推測しない。 ## `observe` ### Request `POST v1/observe`のbodyには、次のJSON objectを使用する。 | Field | JSON type | Presence | | --- | --- | --- | | `path` | canonical absolute Worldspace pathのstring | required | | `depth` | `0`以上`4294967295`以下のinteger | required | ```json { "path": "/items", "depth": 1 } ``` ### Success response Success bodyには、rootの`ObjectObservation`を直接encodeする。 ```json { "object": { "name": "items", "description": "Item collection", "interfaces": [{ "scope": "/", "name": "item-collection-interface-v1" }], "validator": "cm9vdC12YWxpZGF0b3I=" }, "children": [ { "object": { "name": "123", "description": "First item", "interfaces": [{ "scope": "/", "name": "item-interface-v1" }], "ref": "item:123", "validator": "aXRlbS12YWxpZGF0b3I=" } } ] } ``` Responseのpath、name、depth、children completenessは、requestと[3. Protocol](3-protocol.md)に従って検証する。Hostがresource budget内で完全なresponseを構築できない場合は、partial successにせず、`resource_limit_exceeded`を返す。 ## `fetch_interface` ### Request `POST v1/fetch_interface`のbodyには、次のJSON objectを使用する。 | Field | JSON type | Presence | | --- | --- | --- | | `interface` | `InterfaceReference` object | required | ```json { "interface": { "scope": "/", "name": "item-interface-v1" } } ``` ### Success response | Field | JSON type | Presence | | --- | --- | --- | | `interface` | `InterfaceReference` object | required | | `scope_ref` | scope Objectの`ref`を表すstring | optional | | `descriptor` | Interface Descriptor object | required | | `validator` | canonical base64 string | optional | ```json { "interface": { "scope": "/", "name": "item-interface-v1" }, "scope_ref": "world:root", "descriptor": { "format": "wip-interface/1", "types": [], "operations": [] }, "validator": "aW50ZXJmYWNlLXZhbGlkYXRvcg==" } ``` Responseの`interface`は、requestと完全一致しなければならない。`scope_ref`、Descriptor、validatorは、一つのInterface observationとして扱う。 `scope_ref`はscope Objectの`ref`と同じopaque stringであり、base64化しない。Scope Objectが`ref`を持つ場合は含め、持たない場合は省略する。`null`は使用しない。 Scope Objectに`ref`がない場合も、次のresponseはvalidである。 ```json { "interface": { "scope": "/", "name": "item-interface-v1" }, "descriptor": { "format": "wip-interface/1", "types": [], "operations": [] } } ``` `scope_ref`もvalidatorもない観測は許可される。この場合、scopeのidentityは追跡できず、Descriptorは参照の有効期間中immutableとして扱う。 ## `call_operation` ### Request `POST v1/call_operation`のbodyには、次のJSON objectを使用する。 | Field | JSON type | Presence | | --- | --- | --- | | `target` | `Target` object | required | | `interface` | `InterfaceTarget` object | required | | `operation` | Operation名のstring | required | | `arguments` | 選択したOperation declarationに従うobject | required | `Target`は、pathとoptionalなvalidatorを次のfieldで表す。 | Field | JSON type | Presence | | --- | --- | --- | | `path` | canonical absolute Worldspace pathのstring | required | | `validator` | canonical base64 string | optional | `InterfaceTarget`は、参照とその観測metadataを次のfieldで表す。 | Field | JSON type | Presence | | --- | --- | --- | | `reference` | `InterfaceReference` object | required | | `scope_ref` | 観測したscope Objectの`ref`を表すstring | optional | | `validator` | canonical base64 string | optional | ```json { "target": { "path": "/items/current", "validator": "b2JqZWN0LXZhbGlkYXRvcg==" }, "interface": { "reference": { "scope": "/", "name": "item-interface-v1" }, "scope_ref": "world:root", "validator": "aW50ZXJmYWNlLXZhbGlkYXRvcg==" }, "operation": "get_related_item", "arguments": { "relation": "sibling" } } ``` `interface.reference`と`operation`は、別fieldである。表示用の`/::item-interface-v1#get_related_item`を、一つのfieldへencodeしない。`scope_ref`も`InterfaceReference`のmemberや短縮表記の一部にはせず、`InterfaceTarget`の独立したoptional fieldとして送る。 Clientは、`fetch_interface`の観測に`scope_ref`があればコピーし、なければ省略する。`null`や非stringを`scope_ref`に指定したrequestは、`invalid_request`となる。 Validなstringを指定していても、現在のscope Objectの`ref`と一致しない場合は、Protocolの検証順に従って`interface_mismatch`とする。現在の`ref`が欠落している場合も含む。`scope_ref`を省略した場合はscope identity preconditionを適用せず、省略だけを理由に拒否しない。 Hostはまず、Descriptorに依存しない`target`、`interface`、`operation`のshapeを検証する。次に、Protocolのerror precedenceに従って現在のObjectとInterface observationを固定し、そのDescriptorに従って`arguments`をdecodeする。 ### Success response | Field | JSON type | Presence | | --- | --- | --- | | `result` | Operation return TypeExprに従うJSON value | required | | `validator` | 実行後のObject validatorを表すcanonical base64 string | optional | ```json { "result": { "$case": "found", "value": "/items/123" }, "validator": "bmV3LW9iamVjdC12YWxpZGF0b3I=" } ``` `result`のencodingには、requestで指定し、Hostがprecondition確認時に固定したOperation declarationのreturn TypeExprを使用する。 ## Validator Object validatorとInterface validatorは、対応する次のJSON body fieldにcanonical base64としてencodeする。 - `Object.validator` - `Target.validator` - `FetchInterfaceResponse.validator` - `InterfaceTarget.validator` - `CallOperationResponse.validator` WIP validatorを`ETag`、`If-Match`、その他のHTTP headerだけへ移し、body fieldを省略してはならない。 Host、gateway、HTTP cacheは、通常のHTTP representation metadataとして`ETag`等を追加してよい。ただし、その値はWIP validatorとは独立している。ClientはHTTP metadataを、Object identity、Interface observation、Operation preconditionとして解釈しない。 ## Protocol error envelope 各interactionのProtocol failureは、次のexactなJSON objectとしてencodeする。 ```json { "error": { "code": "invalid_arguments", "message": "Required argument `relation` is missing" } } ``` Top-level objectに含めるのは`error`だけである。`error` objectも、次のfieldだけを持つ。 | Field | JSON type | Presence | | --- | --- | --- | | `code` | 下表のstableなsnake_case string | required | | `message` | boundedな人間向け診断string | required | Clientは`message`を分岐に使用しない。Hostは秘密情報、credential、非公開Object、backend path、内部stack traceをmessageへ含めない。 `ProtocolErrorCode`には、次のwire spellingとcanonical HTTP statusを対応付ける。 | Protocol error code | Wire spelling | HTTP status | | --- | --- | --- | | `InvalidRequest` | `invalid_request` | `400 Bad Request` | | `NotFound` | `not_found` | `404 Not Found` | | `InterfaceNotFound` | `interface_not_found` | `404 Not Found` | | `InterfaceMismatch` | `interface_mismatch` | `409 Conflict` | | `OperationNotFound` | `operation_not_found` | `404 Not Found` | | `InvalidArguments` | `invalid_arguments` | `422 Unprocessable Content` | | `ValidatorRequired` | `validator_required` | `428 Precondition Required` | | `ValidatorMismatch` | `validator_mismatch` | `412 Precondition Failed` | | `InterfaceValidatorRequired` | `interface_validator_required` | `428 Precondition Required` | | `InterfaceValidatorMismatch` | `interface_validator_mismatch` | `412 Precondition Failed` | | `PermissionDenied` | `permission_denied` | `403 Forbidden` | | `ResourceLimitExceeded` | `resource_limit_exceeded` | `422 Unprocessable Content` | | `Internal` | `internal` | `500 Internal Server Error` | | `OperationOutcomeUnknown` | `operation_outcome_unknown` | `500 Internal Server Error` | `resource_limit_exceeded`は、WIP Protocolが扱うlogical requestまたはresponseの上限超過を表す。Observation completeness、logical nesting、collection件数等が対象であり、HTTP statusには`422 Unprocessable Content`を使用する。HTTP implementationやdeploymentのmessage-size上限超過を、このcodeへ変換しない。 Rate limitやdeployment concurrency limitによる`429 Too Many Requests`は、Transport / deployment concernである。ValidなProtocol error envelopeがない限り、`ResourceLimitExceeded`へ変換しない。 Hostは、interactionごとに[3. Protocol](3-protocol.md)で許可されたcodeだけを返す。ClientがvalidなProtocol error envelopeを取得した場合、回復actionは`code`に従う。HTTP statusがcanonical mappingと一致しなくても、statusから別codeを推測しない。Status mismatchは、Binding違反として診断してよい。 `InvalidResponse`と`UnsupportedDescriptorFormat`はClient-local classificationであり、Hostがerror envelopeで返してはならない。Domain failureもProtocol errorへ変換せず、Operation return typeに従うApplication dataとしてencodeする。 ## HTTP authentication boundary Authentication方式、credential、mTLS、proxy、gateway等は、HTTP implementationとdeploymentが設定・運用する。このbindingは規定しない。 HTTP layerがWIP interactionを開始せずに返す`401 Unauthorized`や`403 Forbidden`は、validなProtocol error envelopeを持たないTransport failureである。Clientはこれらを`PermissionDenied`へ変換しない。 WIP interactionを開始した後のObject、Interface、Operation visibilityとauthorizationは、Protocol semanticsに従う。Protocolの`PermissionDenied`は、validなWIP error envelopeを持つ`403 Forbidden`であり、HTTP layerのaccess rejectionとは区別する。 ## HTTP replay `3xx` response自体は、WIP successやProtocol failureではなく、Transport failureである。Endpoint discovery、redirect、proxy routingの扱いは、HTTP implementationとdeploymentが決定する。 ただし、これらの機構によって、一つのlogical `call_operation` requestを複数回dispatchしてはならない。Dispatch後にredirect responseを受け取った場合も、methodとbodyを維持して別endpointへ自動再送しない。 ## Dispatchとretry Failureをnot dispatchedとして扱えるのは、requestがHostへ送信されていないとTransport実装が証明できる場合である。送信開始後にresponseを取得できない場合、ClientはHostがrequestを受理した可能性を否定しない。 `observe`と`fetch_interface`の再送とtimeout・retry・cancellation policyは、ClientとHTTP実装が決定する。Response ownershipとProtocol上のcache semanticsは、[4. Client](4-client.md)に従う。 `call_operation`には、次の規則を適用する。 - Redirect、connection retry、HTTP stackのautomatic replay、proxy retryによって再送しない。 - `Retry-After`またはHTTP statusだけを理由に再送しない。 - Response不達またはlocal cancellationを、Operationが未実行またはrollback済みである証拠として扱わない。 - `internal`または`operation_outcome_unknown`を受信しても自動再実行しない。 - 同じOperationを利用者が改めて実行する場合は、Protocolの回復規則に従って必要なObjectまたはInterfaceを再観測する。 HTTP implementationとdeploymentは、失敗した`POST v1/call_operation`を透過的にreplayしない。 ## HTTP facilitiesとの境界 HTTP cache、proxy、gateway、compression、connection管理、TLS、message size、timeout、concurrency、rate limit等の設定と運用は、このbindingの規定対象外である。 HTTP cache metadataは、WIP ClientのKnown Space、Interface cache、Object validator、Interface validatorとは別の機構である。`ETag`、`If-Match`、Age、Last-Modified等を、WIP observationやvalidatorとして解釈しない。それ以外のHTTP cache policyは、HTTP implementationとdeploymentが決定する。 HTTP implementationやdeploymentの都合でrequestやresponseを交換できない場合、ClientはTransport failureとして扱う。WIPはこれらの運用設定を規定せず、そのfailureを`resource_limit_exceeded`その他のProtocol errorへ包み直さない。 ## 非目標 このbindingの定義には、次のものを含めない。 - Host内部のAPI、database、filesystem、queueとの接続方法。 - Endpoint discovery service。 - 固定のauthentication scheme。 - HTTP cacheを使ったWorldspace同期。 - Operation idempotency keyまたはexactly-once execution。 - Operation cancellation protocol。 - Streaming、subscription、server push、WebSocket binding。 - 複数のCore interactionを一つのWIP requestへまとめる共通envelope。 - Domain failureの共通HTTP mapping。