Align protocol runtime with spec boundaries

Move demo leaf echo behavior out of the core protocol runtime, treat procedure IDs as opaque protocol fields, and return direct registered children in endpoint introspection to match the spec.
This commit is contained in:
Michael Mikovsky
2026-04-25 11:27:29 -06:00
parent ba3f28a78c
commit 6bdf59c5c9
13 changed files with 63 additions and 106 deletions
+8 -16
View File
@@ -16,11 +16,11 @@ fn packet_framing_roundtrip_preserves_header_and_payload() {
packet_type: PacketType::Call,
src_path: path(&["root", "caller"]),
dst_path: path(&["root", "callee"]),
dst_leaf: Some("echo".to_owned()),
dst_leaf: Some("service".to_owned()),
hook_id: None,
};
let call = CallMessage {
procedure_id: "unshell.echo.v1.alpha.invoke".to_owned(),
procedure_id: "example.service.v1.invoke".to_owned(),
data: vec![1, 2, 3, 4],
response_hook: Some(HookTarget {
hook_id: 7,
@@ -45,7 +45,7 @@ fn header_and_call_validation_reject_invalid_combinations() {
packet_type: PacketType::Data,
src_path: path(&["peer"]),
dst_path: path(&["host"]),
dst_leaf: Some("echo".to_owned()),
dst_leaf: Some("service".to_owned()),
hook_id: None,
};
assert_eq!(
@@ -59,11 +59,11 @@ fn header_and_call_validation_reject_invalid_combinations() {
packet_type: PacketType::Call,
src_path: path(&["caller"]),
dst_path: path(&["callee"]),
dst_leaf: Some("echo".to_owned()),
dst_leaf: Some("service".to_owned()),
hook_id: None,
};
let invalid_call = CallMessage {
procedure_id: "unshell.echo.v1.alpha.invoke".to_owned(),
procedure_id: "example.service.v1.invoke".to_owned(),
data: Vec::new(),
response_hook: Some(HookTarget {
hook_id: 5,
@@ -79,18 +79,10 @@ fn header_and_call_validation_reject_invalid_combinations() {
}
#[test]
fn procedure_validation_accepts_introspection_and_rejects_bad_shapes() {
fn procedure_validation_accepts_introspection_and_non_empty_opaque_ids() {
assert_eq!(validate_procedure_id(""), Ok(()));
assert_eq!(
validate_procedure_id("unshell.echo.v01.alpha.invoke"),
Ok(())
);
assert_eq!(
validate_procedure_id("contains spaces"),
Err(ValidationError::ProcedureId(
"procedure identifier should use alphanumeric characters, dots, and underscores"
))
);
assert_eq!(validate_procedure_id("example.service.v01.invoke"), Ok(()));
assert_eq!(validate_procedure_id("contains spaces"), Ok(()));
}
#[test]
+11 -11
View File
@@ -1,7 +1,7 @@
use alloc::{borrow::ToOwned, string::String, vec, vec::Vec};
use crate::protocol::tree::{
DefaultRouteProvider, Endpoint, Ingress, LeafBehavior, LeafNode, LeafSpec, LocalEvent,
ChildRoute, DefaultRouteProvider, Endpoint, Ingress, LeafNode, LeafSpec, LocalEvent,
ProtocolEndpoint, RouteDecision, RouteProvider, TreeNode,
};
use crate::protocol::{
@@ -19,8 +19,8 @@ fn tree_node_paths_flatten_explicitly() {
children: vec![TreeNode::Endpoint {
segment: "branch".to_owned(),
leaves: vec![LeafNode {
name: "echo".to_owned(),
procedures: vec!["unshell.echo.v1.alpha.invoke".to_owned()],
name: "service".to_owned(),
procedures: vec!["example.service.v1.invoke".to_owned()],
}],
children: vec![TreeNode::Endpoint {
segment: "leaf".to_owned(),
@@ -60,11 +60,10 @@ fn protocol_endpoint_introspection_returns_leaf_summary() {
let mut endpoint = ProtocolEndpoint::new(
path(&["root"]),
Some(Vec::new()),
Vec::new(),
vec![ChildRoute::registered(path(&["root", "child"]))],
vec![LeafSpec {
name: "echo".to_owned(),
procedures: vec!["unshell.echo.v1.alpha.invoke".to_owned()],
behavior: LeafBehavior::Echo,
name: "service".to_owned(),
procedures: vec!["example.service.v1.invoke".to_owned()],
}],
);
@@ -96,11 +95,12 @@ fn protocol_endpoint_introspection_returns_leaf_summary() {
.expect("introspection payload should deserialize");
assert!(response.end_hook);
assert_eq!(introspection.sub_endpoints, vec!["child".to_owned()]);
assert_eq!(introspection.leaves.len(), 1);
assert_eq!(introspection.leaves[0].leaf_name, "echo");
assert_eq!(introspection.leaves[0].leaf_name, "service");
assert_eq!(
introspection.leaves[0].procedures,
vec!["unshell.echo.v1.alpha.invoke".to_owned()]
vec!["example.service.v1.invoke".to_owned()]
);
}
@@ -113,7 +113,7 @@ fn invalid_hook_peer_emits_local_fault_event() {
.make_call(
path(&["server"]),
None,
"unshell.echo.v1.alpha.invoke",
"example.service.v1.invoke",
Some(hook_id),
vec![1, 2, 3],
)
@@ -128,7 +128,7 @@ fn invalid_hook_peer_emits_local_fault_event() {
hook_id: Some(hook_id),
},
&DataMessage {
procedure_id: "unshell.echo.v1.alpha.invoke".to_owned(),
procedure_id: "example.service.v1.invoke".to_owned(),
data: vec![9],
end_hook: false,
},