feat: add Astro reference site and organize book contents
Reference site / build (push) Canceled after 0s

This commit is contained in:
2026-10-09 23:40:37 +09:00
parent 6086f3c5ef
commit 01c9498e6d
39 changed files with 7772 additions and 0 deletions
+498
View File
@@ -0,0 +1,498 @@
# Rust API Model
## Status
この文書は、WIP HostをRustで実装するための概念的なAPI modelを整理するdraftである。
このdraftで示すtrait名、attribute、derive、generated type名、method signatureは説明用であり、具体的なRust API syntaxとして確定しない。Ownership、lifetime、async runtime、error type、macro crate構成も未決定である。
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するTypeScript modelは[TypeScript API Model](typescript-api-model.md)を参照する。
## 目的
Rust APIでは、次のmodelを自然に表現できるようにする。
1. Rust traitでWIP Interfaceを宣言する。
2. Rust structが、Protocol Objectとして公開するmetadataを提供する。
3. 同じstructが、必要に応じて公開する0個以上のInterface traitを実装する。
4. Objectを返す時点で、公開するInterfaceのordered setを明示的に選択する。
5. Trait declarationからInterface Descriptor、Value codec、validation、Operation dispatchに必要なcodeを生成する。
6. Struct instanceをWorldspace全体について常駐させず、`observe`と`call_operation`の解決時にdata-drivenに生成できる。
このmodelでは、Protocol上のObjectとInterfaceの関連付けは`Object.interfaces`だけで表す。Operation implementationへ到達するためのRust内部codeはSDK / Host Runtimeの実装詳細であり、新しいProtocol conceptを導入しない。
## Conceptual model
### Interface trait
WIP InterfaceはRust traitとして宣言する。
```rust
#[wip::interface]
trait FileInterface {
/// Reads bytes from the file.
async fn read(
&self,
/// Byte offset from the beginning of the file.
offset: Option<i64>,
/// Maximum number of bytes to return.
length: Option<i64>,
) -> Bytes;
/// Replaces the file contents.
async fn write(
&self,
content: Bytes,
) -> WriteResult;
}
```
このcodeはconceptual syntaxである。`Option<i64>`の対応範囲、`Bytes` wrapper、documentationの取得方法、async methodとerrorの具体形は別途決定する。
Trait declarationは、次のlogical declarationに対応する。
- 一つのtrait declarationを、一つのInterface Descriptorを生成するRust側definitionとして扱う。
- Trait名はgenerated Rust itemやlocal registrationを識別するために使用できるが、Protocol `InterfaceDescriptor`のfieldや構造化されたInterface参照としてそのまま公開しない。
- Trait methodをOperation Declarationとして扱う。
- ReceiverはProtocol parameterに含めない。
- Method parameterを名前付きOperation parameterとして扱う。
- Return typeをOperation return typeとして扱う。
- Rust typeをDescriptorの`TypeExpr`とProtocol `Value`へ対応付ける。
- Documentationをtrait、method、parameter、return、関連typeから取得できるようにする。
Descriptorのshapeはtrait declarationによって決まり、各structのtrait implementationによって変化しない。
### Object implementation
Rust structは、その時点でWorldspaceへ投影するObjectをHost内部で表現できる。
```rust
struct File {
name: String,
path: PathBuf,
reference: Option<String>,
validator: Option<Vec<u8>>,
}
```
Structは概念上の`WipObject` traitを実装する。
```rust
impl WipObject for File {
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
None
}
fn reference(&self) -> Option<&str> {
self.reference.as_deref()
}
fn validator(&self) -> Option<&[u8]> {
self.validator.as_deref()
}
}
```
`WipObject`が返す値のownershipやborrow形式は未決定である。概念的にはProtocol Objectのうち、publication時に選択するInterface集合以外の公開metadataを提供する。
`WipObject`がProtocol metadataとして返す値へ次を含めない。これらをimplementing structのprivate fieldとして保持することは禁止しない。
- Absolute path。PathはObjectのfieldではなく、Worldspace resolutionのcontextである。
- Children。ChildrenはTree上の配置contextである。
- 固定されたInterface集合。InterfaceはObjectを公開する時点で追加する。
- Backend connection、file descriptor、credential等のHost-private state。
Structが保持する`path`やbackend handle等はHost内部のOperation implementationに使用できるが、`WipObject`のmetadataまたはProtocol Objectへ自動的にserializeしない。
### Interface implementation
Object implementationとして使用するstructは、公開したいInterface traitを実装する。
```rust
impl FileInterface for File {
async fn read(
&self,
offset: Option<i64>,
length: Option<i64>,
) -> Bytes {
// self.pathが示す現在のfileを読む
}
async fn write(
&self,
content: Bytes,
) -> WriteResult {
// self.pathが示す現在のfileへ書く
}
}
```
Trait implementationはOperationのbehaviorを提供する。Interface Descriptorはtrait implementationから生成せず、Interface trait declarationから生成する。
Rustには、あるtypeが実装しているtraitを列挙する一般的なreflectionがない。また、一つのstructが複数のInterface traitを実装し得る。そのため、trait implementationが存在するだけでInterfaceを暗黙に公開しない。
### Object publication
ObjectをWorldspaceへ返す時点で、struct instanceと公開する0個以上のInterface Declarationを明示的に組み合わせる。Interfaceは追加順を保持するordered setであり、同じDefinitionを重複して追加しない。
Conceptual syntaxは次のようになる。
```rust
let file = File::resolve(path).await?;
let object = PublishedObject::new(file)
.expose(FileInterfaceDefinition);
```
ここで各`InterfaceDefinition`は、`#[wip::interface]`が生成するconceptualなcompanion definitionである。実際の名前や、associated item、module、valueのどの形で生成するかは未決定である。
Publication APIは、追加する各Definitionについて概念的に次のboundを要求する。
```rust
impl<T: WipObject> PublishedObject<T> {
fn expose<I>(self, interface: I) -> Self
where
I: InterfaceDefinition<T>;
}
impl<T: FileInterface> InterfaceDefinition<T>
for FileInterfaceDefinition
{
// generated registration and dispatch metadata
}
```
このboundにより、Objectへ追加する各Interfaceについて、公開する値がObject metadataとOperation implementationの両方を提供することをcompile timeに確認できる。どのInterfaceも追加しないObjectも表現できる。
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeとして追加しない。Host Runtimeはこれを使用して次を構築する。
```rust
Object {
name: object.name(),
description: object.description(),
interfaces: selected_interface_references,
r#ref: object.reference(),
validator: object.validator(),
}
```
`selected_interface_references`は、Hostが各generated Interface Definitionを登録または公開するときに割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べたものである。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Macroが参照をcompile timeに固定することは要求しない。
`observe`はDescriptor自体をObjectへ埋め込まず、このInterface参照のordered setだけを返す。Clientが各参照を`fetch_interface`したとき、Host Runtimeはtrait declarationから生成されたDescriptorと、存在する場合はInterface validatorを返す。同じ参照とvalidatorの組のDescriptorはHost上で共有およびcacheできるため、Object instanceごとにDescriptorを再生成または再送する必要はない。
## Macroが生成する責務
`#[wip::interface]`は、conceptualには次を生成または提供する。
- Interface Descriptorを構築するdefinition。
- Trait methodとOperation Declarationの対応情報。
- ArgumentsのProtocol `Value` decoder。
- ResultのProtocol `Value` encoder。
- Argumentsとresultのruntime validation。
- Operation名から対応するtrait methodを呼び出すdispatch code。
- 任意の`T: WipObject + InterfaceTrait`について、そのInterfaceを`PublishedObject<T>`へ追加するための型付きentry point。
- HostがInterface参照、optional validator、Descriptorを登録、取得、cacheするためのidentity。
MacroがRust codebase内のtrait implementationを探索または列挙することは要求しない。Publication時のgeneric boundによって、対象structがInterface traitを実装していることを確認する。
Generated dispatch codeはRust SDK内部の実装詳細である。Host内部のdispatch mechanismやRust type名等をProtocolへ公開しない。
## Rust typeとProtocol type
Interface traitで使用できるRust typeは、Descriptorの`TypeExpr`とProtocol `Value`へ対応付けられなければならない。
Conceptualにはderiveまたは明示的なcodec implementationを使用する。
```rust
#[derive(WipType)]
struct WriteResult {
bytes_written: i64,
}
```
```rust
#[derive(WipType)]
enum ReadResult {
Data { content: Bytes },
EndOfFile,
}
```
このsyntaxも未決定である。少なくとも次を表現できる必要がある。
- Unit、Boolean、Integer、Number、String、Bytes、Json、Entry。
- Record、List、Enum、Union。
- Descriptor内のNamed type。
- Requiredとoptionalなfieldおよびparameter。
- Documentation。
Rustの`Option<T>`をoptional field / parameter以外で許可するか、enumをProtocol EnumまたはUnionへどう対応付けるか、newtypeをどのように扱うかは未決定である。
Rust SDKは、integerのProtocol相互運用範囲、finite number、unknown field、Union shape、Entry path等をProtocol boundaryで検証しなければならない。
## Dynamic Worldspaceでのlifecycle
### `observe`
Projection implementationはrequest時にbackend dataを解決し、struct instanceを生成する。
```rust
async fn resolve_file(path: &WipPath) -> Result<PublishedObject> {
let stat = filesystem.stat(path).await?;
let file = File {
name: stat.name,
path: stat.path,
reference: make_reference(&stat),
validator: make_validator(&stat),
};
Ok(PublishedObject::new(file)
.expose(FileInterfaceDefinition))
}
```
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Response生成後にこの`File` instanceを破棄してよく、Worldspace内の全fileに対応するinstanceを保持しない。
Requested depthが正の場合、Directory listingで発見した各entryについて、その時点のstruct instanceを生成して公開できる。Providerがdirectory全体を先に収集してから`Vec`として返すことは要求しないが、一つのparentのobservationを成功させるには公開されたindexable childrenをclean exhaustionまで列挙しなければならない。
```rust
let mut entries = filesystem.discover_children(path, budget).await?;
while let Some(entry) = entries.next().await? {
let Some(child) = project_current_object(
entry.path(),
context,
).await? else {
continue;
};
observation.push_child(child)?;
}
```
`discover_children`、`budget`、`observation`はconceptualであり、具体APIではない。必要なsemanticsは次である。
- 各childを現在の主体についてprojectし、非公開Objectとそのsubtreeを返さない。
- 公開されたindexable childrenをすべて列挙し、clean exhaustionで終了する。
- Backend failure、cancellation、resource budget超過をclean exhaustionとして扱わず、部分的なsuccess responseを返さない。
- Requested depthに達したnodeではchild discoveryを行わず、`children`を未観測として省略する。
- 異なるconcrete published typeを、Providerから共通のreturn typeとして扱える。
具体的なreturn type、internal streaming、backpressure、type erasure、error propagationは未決定である。
### `call_operation`
Hostはcall時に、requestのTargetと`InterfaceTarget`をHost Runtimeへ渡す。Runtimeは一つのatomic execution boundaryへ入ってから`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
```rust
runtime.call_current(
target,
interface,
operation,
arguments,
context,
|path, context| resolve_current_projection(path, context),
).await
```
`resolve_current_projection`と`runtime.call_current`というAPIを採用することは決定しない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、返す値はそのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む必要がある。このexampleが示す要件は次である。
- 過去の`observe`で作成したstruct instanceを保持していなくてもOperationを実行できる。
- Call時の現在の主体、Object visibility、Object metadata、Interface集合を同じProjection pathで再解決し、Objectが非公開なら`NotFound`を返す。
- Requestの`interface.reference`が現在の`Object.interfaces`に含まれ、self-scopeを含む祖先制約を満たすことを確認する。指定された`interface.scope_ref`と現在のscope Objectの`ref`も照合し、満たせない場合は`InterfaceMismatch`を返す。`scope_ref`の省略だけでは拒否しない。
- 現在のInterfaceにOperationが宣言されていなければ`OperationNotFound`、Operationを公開しつつ実行だけを拒否する場合は`PermissionDenied`を返す。
- `interface.validator`を現在のInterface validatorへ照合する。Mutable Interfaceにvalidatorがなければ`InterfaceValidatorRequired`、不一致なら`InterfaceValidatorMismatch`を返す。
- 現在のProjected Object、Object validator、選択されたInterfaceとそのvalidator、Descriptor、Operation、Rust側のObject implementation、実際のbackend対象を一つのexecution boundary内で一致させる。
- Object validatorが指定されている場合は、現在のObject identityと保護対象状態の両方へ照合し、同じexecution boundary内でOperationを実行する。
- Pathが別Objectを指す場合は、provider-local revisionや内容が同じでもObject validatorを一致させない。
- Providerのvalidatorがobject-localなrevisionだけの場合、HostはObject identityを含む形へnamespace化またはwrapできなければならない。
- Object validatorが省略され、Operationがvalidatorを要求する場合は、実行せず`ValidatorRequired`を返す。
- Object validatorなしの実行をOperationが許可する場合は、実行時にpathが指す現在Objectへ無条件に実行する。
- Macro-generated dispatchが、選択されたInterface traitのmethodを現在のstruct instanceに対して呼び出す。異なるInterfaceの同名Operationをmergeまたは曖昧に解決しない。
- Operation実行後の現在状態に対応するvalidatorを、必要に応じて`CallOperationResponse`へ返せる。
Object validatorをObject identityへ結び付けるためにClient-facingな`ref`を要求しない。ProviderまたはHostはHost-privateなidentityを使用できるが、そのidentity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとOperation implementationの固定、authorization、Operation実行を一つのatomic boundaryで行う。
Operation実行後validatorを、同じstruct instanceから再計算するか、Operation resultとともに返すか、backendを再観測するかは未決定である。どの方式でも、resultを生成した実行後状態とvalidatorを対応させなければならない。
Structが`PathBuf`だけを保持し、validator比較後にpathを無条件で開き直す実装は、対象差し替えに対するatomicityを保証できない場合がある。Rust APIは、file descriptor、transaction、conditional update、lock等を利用してbackend固有のatomicityを実現できる必要があるが、その抽象化は未決定である。
## 複数Interfaceの実装
一つのstructは複数のInterface traitを実装できる。
```rust
impl ReadOnlyFileInterface for File {
// ...
}
impl WritableFileInterface for File {
// ...
}
```
Publication時に、現在の主体へ公開する0個以上のInterfaceを選択し、表示したい順で追加する。
```rust
let mut object = PublishedObject::new(file)
.expose(ReadOnlyFileInterfaceDefinition);
if authorization.can_write() {
object = object.expose(WritableFileInterfaceDefinition);
}
object
```
Protocol Objectの`interfaces`は追加順を保持するordered setである。同じInterface参照の重複は拒否する。各Interface Descriptorは独立したOperation集合を宣言し、複数trait implementationを一つのDescriptorへ暗黙にmergeしない。
異なるInterfaceは同じOperation名を宣言できる。Dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まり、表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従う。Signature全体をProtocol request fieldへparseし直さない。
Rust traitのsupertrait、trait alias、複数traitの組み合わせをDescriptor生成へどう対応付けるかは未決定であり、Protocol上のInterface inheritanceを暗黙に導入しない。
## 固定Interface向けのsugar
一つのRust typeを常に同じInterface集合で公開する場合、次のようなsugarを追加してよい。
```rust
#[wip::object(interfaces = [ReadOnlyFileInterface, WritableFileInterface])]
struct File {
// ...
}
```
または、conceptualには`WipObject`のassociated itemとしてdefault Interface集合を指定できる。
ただし、固定Interface集合をcore modelにはしない。主体、policy、resource kind等に基づいて同じstructへ異なるInterface subsetを追加できるexplicit publication modelを基礎とする。
Sugarを使用する場合も、対象typeが指定されたすべてのInterface traitを実装していることと、同じInterfaceを重複していないことを確認しなければならない。
## HostへのInterface登録
Generated Interface DefinitionをHostへ登録し、構造化されたInterface参照を割り当てる必要がある。
参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。以下のconceptual API例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めるものではない。登録時のcontextと引数の具体APIは引き続き未決定である。Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証し、`ref`がない場合のidentity追跡不能も許容する。Scopeの移動追跡や独立したscope validatorを導入しない。
Conceptualには、eager registrationとlazy registrationの両方が考えられる。
```rust
let file_read_interface = host.register_interface(ReadOnlyFileInterfaceDefinition)?;
let file_write_interface = host.register_interface(WritableFileInterfaceDefinition)?;
let object = PublishedObject::new(file)
.expose(file_read_interface)
.expose(file_write_interface);
```
または、Hostが最初のpublication時に各definitionをinternしてよい。
どちらの場合も次を守る。
- MutableなInterface参照では`fetch_interface`がvalidatorを返し、同じ参照とvalidatorの組から異なるDescriptorを返さない。
- Validatorを返さないInterface参照は、その参照の有効期間中Descriptorをimmutableにする。
- Descriptorを更新する場合は同じ参照へ新しいvalidatorを発行するか、新しいInterface参照を使用する。
- Objectの`interfaces`へ設定した各Interface参照のDescriptorを、その主体から`fetch_interface`できる。
- 一つのObjectへ同じInterface参照を重複して追加しない。
- 構造的に同じDescriptorを同じ参照へdeduplicateすることは要求しない。
- Rust type名やprocess-local addressを、そのままportableなProtocol semanticsとして扱わない。
## Request contextとauthorization
Operation implementationは、Object instance以外にrequest contextを必要とし得る。
- 現在の主体。
- Cancellationとdeadline。
- Tracing / audit context。
- Host serviceやbackend connectionへのaccess。
- Resource limit。
これらをmethod parameter、receiver wrapper、generated context、task-local stateのどれで渡すかは未決定である。Protocol parameterとして宣言された値と、Hostが注入するcontextを明確に区別しなければならない。
Object publication時のInterface集合の選択と、Operation call時のmembership、Interface validator、authorizationの再評価を実装できる必要がある。以前の`observe`で公開されたInterface集合だけを根拠に、現在のOperation実行を許可してはならない。
Operation resultのRecord、List、Union等へnestedしたすべての`Entry`位置について、Hostは現在の主体にそのpathを認識させてよいことを再帰的に確認できなければならない。通常のstructural Value validationだけではこのvisibility checkを満たさない。Macro-generated code、Projection、Host Runtimeのどこで確認するかは未決定である。
Operation argumentとして`Entry` pathを受け取った場合も、pathの所持をauthorizationの証明として扱わず、参照先へ作用する時点で現在の主体について認可する。
## Error model
Rust methodのerror表現は、次の四種類を区別できなければならない。
- Protocol validationまたはdispatch failure。
- Effectがcommitされていないと保証できるHost / backend implementation failure。
- Operationの未実行またはrollbackを保証できない`OperationOutcomeUnknown`。
- Interfaceがreturn typeとして宣言したdomain failure。
現在のProtocolでは、domain failureはOperation resultのUnion caseとして表す。Rustの`Result<T, E>`をdomain Union、Host error、または両方のどれへ対応付けるかは未決定である。
MacroがRust panic、result encode failure、宣言型に違反するimplementation resultをdomain failureへ自動変換してはならない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できない場合は`OperationOutcomeUnknown`へmappingする。Clientへ送信済みか不明なtransport切断も自動retryしない。
## 要件
Rust API modelは少なくとも次を満たす。
- Interface Descriptorをtrait declarationから生成し、trait implementationごとに変化させない。
- Structが`WipObject`と、追加する各Interface traitを実装していることをcompile timeに確認する。
- 0個以上のInterfaceをpublication時に明示し、実装済みtraitの自動列挙に依存しない。
- Objectのpath、children、Interface集合をstructへ恒久的に固定しない。
- Struct instanceをrequest scopeで生成および破棄できる。
- 全Object instanceの事前登録を要求しない。
- Direct childrenを現在の主体についてprojectし、非公開Objectとそのsubtreeを除外しつつlazyに発見し、success responseではclean exhaustionまで列挙する。
- Backend failure、cancellation、resource budget超過をclean exhaustionとして扱わず、部分的なobservationをsuccess responseとして返さない。
- 同じstructへ複数のInterfaceを同時に追加でき、追加順を保持し、重複を拒否できる。
- 異なるInterfaceの同名Operationを、Interface参照とOperation名の組でdispatchできる。
- Protocol boundaryでarguments、result、Object、Descriptorを検証する。
- Operation result内のnestedな`Entry`へ、現在の主体についてvisibility checkを適用できる。
- Host-private fieldをProtocol ObjectまたはValueへ暗黙にserializeしない。
- Call時の現在の主体、Object visibility、Object validator、Interface membershipとvalidator、Descriptor、Operation、Rust側implementation、backend対象を一貫したexecution boundaryで扱う。
- 非公開Object、Interface非membership、非公開Operation、公開済みOperationの実行拒否をそれぞれ`NotFound`、`InterfaceMismatch`、`OperationNotFound`、`PermissionDenied`へ対応付ける。
- Interface validatorの必須・不一致を`InterfaceValidatorRequired`、`InterfaceValidatorMismatch`へ対応付ける。
- Object validatorを現在のObject identityと保護対象状態へ結び付け、別Objectに同じprovider-local revisionがあっても一致させない。
- Object validator比較、identity confirmation、Interface membershipとvalidator比較、DescriptorとOperation実装の固定、authorization、Operation実行を同じatomic boundaryで行う。
- Object validatorを要求するOperationへの省略を`ValidatorRequired`として拒否できる。
- Provider、Host Runtime、macro-generated codeのerrorを、effect未commitを保証できる`Internal`と、保証できない`OperationOutcomeUnknown`へ安全に対応付けられる。
- InvalidなObject、Descriptor、Operation resultをsuccess responseとして送信せず、Host-side validation failureをdomain failureへ変換しない。
- Rust SDK固有の型やlifetimeをProtocol semanticsとして要求しない。
## 非目標
このdraftは次を決定しない。
- 最終的なcrate、module、trait、attribute、deriveの名前。
- Proc macroの内部実装。
- 特定のasync runtime。
- Object instanceの常駐registryまたはactor model。
- Rust trait objectをwireへ公開すること。
- Rust trait inheritanceをProtocol Interface inheritanceとして扱うこと。
- Backend entityとRust structまたはProtocol Objectの一対一対応。
- Client SDKのtyped proxy API。
## 未決定事項
- `WipObject`の具体的なmethodとmetadata ownership。
- Object metadata取得をsyncまたはasyncのどちらにするか。
- Publication APIがObject instanceをown、borrow、`Arc`化するか。
- Generated Interface Definitionの具体的なRust表現。
- Interface登録とscope / local name割当のlifecycle。
- Trait、Operation、parameter名のrename規則。
- Rust doc commentとProtocol Documentationの対応。
- Supported Rust typeと`TypeExpr`の対応。
- `Option<T>`を許可する位置。
- Generic method、associated type、lifetime parameterをInterface traitで許可するか。
- `&self`、`&mut self`、owned receiverのどれをOperationで許可するか。
- Async methodをnative syntax、generated boxed future、別macroのどれで扱うか。
- Request contextとProtocol parameterのAPI上の分離。
- Nestedな`Entry` resultのvisibility checkをMacro-generated code、Projection、Host Runtimeのどこで行うか。
- Domain failure、Host error、panicのRust上の表現。
- Macro-generated dispatchとHost Runtimeの責務境界。
- Published ObjectをProviderから返す際のtype erasure。
- Validator比較とOperation実行を囲むbackend-specificなatomicity abstraction。
- Provider-local validatorをObject identityへnamespace化またはwrapするHost API。
- Operation実行後validatorをObject instance、Operation implementation、Providerのどこから取得するか。
- 主体ごとに異なるInterface combinationを追加したPublished Objectのconcrete return typeをどう統一するか。
- Rust client APIを同じtrait declarationから生成するか。
これらを決定する際は、静的service objectだけでなく、Filesystem、database row、virtual aggregate、主体別Interface compositionを同じAPIで実装できるか評価する。