feat: migrate protocol and HTTP to structured interface references

T-20: identify interfaces by exact scope/name pairs; add optional opaque scope_ref metadata and separate shape validation from path-dependent scope compatibility. Preserve call error precedence, strict JSON, validators and transport boundaries. Mechanically migrate consumers and document API/wire compatibility and deferred lifecycle semantics.

Validation: cargo fmt --all --check; git diff --check; cargo check --workspace --all-targets; cargo test -p wip-protocol -p wip-http; cargo test --workspace (221 passing tests including doctests); cargo test --workspace --all-targets; nix develop --command cargo clippy --workspace --all-targets -- -D warnings; RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps. All pass. cargo/rustc 1.95.0; development-shell Clippy/rustc 1.97.1.
This commit is contained in:
2026-10-07 18:29:51 +09:00
parent bf5fa54f44
commit 8ecc307fc9
34 changed files with 2124 additions and 263 deletions
+29 -13
View File
@@ -1,3 +1,10 @@
fn root_reference(name: &str) -> wip_protocol::InterfaceReference {
wip_protocol::InterfaceReference {
scope: "/".into(),
name: name.into(),
}
}
use std::collections::BTreeMap;
use wip_client::{
@@ -39,7 +46,7 @@ fn object() -> Object {
Object {
name: "item".into(),
description: None,
interfaces: vec!["math".into()],
interfaces: vec![root_reference("math")],
r#ref: None,
validator: Some(b"object-v1".to_vec()),
}
@@ -72,7 +79,7 @@ fn malformed_json_unknown_fields_duplicates_and_invalid_success_are_invalid_resp
let cases: &[&[u8]] = &[
b"{not json",
br#"{"name":"item","interfaces":[],"unknown":true}"#,
br#"{"name":"item","interfaces":["math","math"]}"#,
br#"{"name":"item","interfaces":[{"scope":"/","name":"math"},{"scope":"/","name":"math"}]}"#,
br#"{"name":"wrong","interfaces":[]}"#,
];
for body in cases {
@@ -181,12 +188,15 @@ fn non_success_without_valid_envelope_remains_transport_failure() {
#[test]
fn unsupported_descriptor_format_is_distinct_from_invalid_response() {
let (mut client, session) = setup();
let request = client.prepare_interface(&session, "math").unwrap();
let request = client
.prepare_interface(&session, root_reference("math"))
.unwrap();
let logical = FetchInterfaceRequest {
interface: "math".into(),
interface: root_reference("math"),
};
let value = FetchInterfaceResponse {
interface: "math".into(),
scope_ref: None,
interface: root_reference("math"),
descriptor: descriptor("future-format/2"),
validator: Some(b"v2".to_vec()),
};
@@ -216,16 +226,19 @@ fn malformed_call_success_after_dispatch_is_outcome_unknown_and_stales_object()
.unwrap(),
)
.unwrap();
let interface = client.prepare_interface(&session, "math").unwrap();
let interface = client
.prepare_interface(&session, root_reference("math"))
.unwrap();
client
.complete(
interface.id,
encode_fetch_interface_response(
&FetchInterfaceRequest {
interface: "math".into(),
interface: root_reference("math"),
},
&FetchInterfaceResponse {
interface: "math".into(),
scope_ref: None,
interface: root_reference("math"),
descriptor: descriptor(INTERFACE_FORMAT_V1),
validator: None,
},
@@ -238,7 +251,7 @@ fn malformed_call_success_after_dispatch_is_outcome_unknown_and_stales_object()
.prepare_call(
&session,
"/item",
"math",
&root_reference("math"),
"calculate",
BTreeMap::from([("value".into(), Value::Integer(2))]),
)
@@ -293,16 +306,19 @@ fn plain_413_after_call_dispatch_is_unknown_transport_outcome() {
.unwrap(),
)
.unwrap();
let interface = client.prepare_interface(&session, "math").unwrap();
let interface = client
.prepare_interface(&session, root_reference("math"))
.unwrap();
client
.complete(
interface.id,
encode_fetch_interface_response(
&FetchInterfaceRequest {
interface: "math".into(),
interface: root_reference("math"),
},
&FetchInterfaceResponse {
interface: "math".into(),
scope_ref: None,
interface: root_reference("math"),
descriptor: descriptor(INTERFACE_FORMAT_V1),
validator: None,
},
@@ -315,7 +331,7 @@ fn plain_413_after_call_dispatch_is_unknown_transport_outcome() {
.prepare_call(
&session,
"/item",
"math",
&root_reference("math"),
"calculate",
BTreeMap::from([("value".into(), Value::Integer(2))]),
)