Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions crates/busbar-kernel/src/plane_driver/far_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,23 @@ fn class_code(class: Option<WireStatusClass>) -> u32 {

/// `base_url` + the plane's target: the base's trailing `/` trimmed, then the target as the plane
/// answered it.
///
/// A web base URL's `\` is read as `/` first, as the dialler's WHATWG reader reads it and as v1.5.5
/// folded it before signing (`crates/busbar/src/proxy/egress.rs:18`, `host_from_base`), so the
/// authority the auth call signs, the head's path and the host dialled come off ONE spelling: a
/// backslash-blind split of `https://evil.example\@victim.example/` signed one host while the
/// stack dialled another.
fn join(base: &str, target: &[u8]) -> String {
let base: std::borrow::Cow<'_, str> = match base.split_once("://") {
Some((scheme, _))
if base.contains('\\')
&& busbar_contract::net::UrlFamily::of(&scheme.to_ascii_lowercase())
== busbar_contract::net::UrlFamily::Web =>
{
std::borrow::Cow::Owned(base.replace('\\', "/"))
}
_ => std::borrow::Cow::Borrowed(base),
};
format!(
"{}{}",
base.trim_end_matches('/'),
Expand Down
41 changes: 30 additions & 11 deletions crates/busbar-kernel/src/plane_driver/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,17 +1184,13 @@ impl<S: AttemptSteps, F: FarEnd, C: CallerEnd> super::PlaneUnits<'_, S, F, C> {
// hook chose the serving member, after the plane's own fields, as 1.5.5
// stamped them; nothing on the default path or when no hook chose.
let chosen = self.lock().route_policy;
if let Some(name) = chosen.filter(|_| {
!bufs.member.is_empty() && crate::proxy::route_policy_headers_enabled()
}) {
fields.push((
crate::proxy::HDR_ROUTE_POLICY.as_bytes().to_vec(),
name.as_bytes().to_vec(),
));
fields.push((
crate::proxy::HDR_ROUTE_TARGET.as_bytes().to_vec(),
bufs.member.clone(),
));
if chosen.is_some() {
route_policy_fields(
&mut fields,
crate::proxy::route_policy_headers_enabled(),
chosen,
&bufs.member,
);
}
self.caller.head(out.reply_status, fields);
// The answer's head is the `response` stage (1.5.5 fires it at head time,
Expand Down Expand Up @@ -1243,6 +1239,29 @@ impl<S: AttemptSteps, F: FarEnd, C: CallerEnd> super::PlaneUnits<'_, S, F, C> {
}
}

/// THE ROUTE-POLICY TRANSPARENCY FIELDS (opt-in, `advanced.response_headers.route_policy`), as
/// 1.5.5's `maybe_attach_route_policy_gated` gated them: the pair goes after the plane's own fields
/// only when the operator opted in (`enabled`, the outer gate) AND a non-default policy chose the
/// serving member (`policy`, the inner gate), naming the policy and the member; a local answer
/// (no member) and every other combination add nothing.
fn route_policy_fields(
fields: &mut HeadFields,
enabled: bool,
policy: Option<&str>,
member: &[u8],
) {
if let Some(name) = policy.filter(|_| enabled && !member.is_empty()) {
fields.push((
crate::proxy::HDR_ROUTE_POLICY.as_bytes().to_vec(),
name.as_bytes().to_vec(),
));
fields.push((
crate::proxy::HDR_ROUTE_TARGET.as_bytes().to_vec(),
member.to_vec(),
));
}
}

/// The duplex session's two sides, on this pump (K6): a child module, so it drives the pump's own
/// pieces and push.
#[path = "session.rs"]
Expand Down
85 changes: 85 additions & 0 deletions crates/busbar-kernel/src/plane_driver/tests/far_end_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,91 @@ async fn a_plane_field_name_that_is_not_a_token_is_refused_before_the_dial() {
assert!(r.book.observed.lock().unwrap().is_empty());
}

/// F25 row 75: rehomed from crates/busbar-llm/src/engine/tests/auth_style_tests.rs::
/// test_host_from_base_backslash_authority_matches_wire_host (its signed-host half; the dialler's
/// reading of each URL is pinned in busbar-kernel-egress's `net_tests`). A WHATWG reader ends a web
/// URL's authority at the first `\` exactly as at `/`, so the host the auth call signs must be the
/// host the connection dials, byte for byte, never the post-`@` host a backslash-blind split reads
/// (v1.5.5 `crates/busbar/src/proxy/egress.rs:18`, `host_from_base`); the port survives and the
/// backslash path rides the head as a path.
#[tokio::test]
async fn test_host_from_base_backslash_authority_matches_wire_host() {
for (base, script_host, authority, host, port, head_path) in [
(
"https://evil.example.com\\@victim.example/path",
"evil.example.com",
"evil.example.com",
"evil.example.com",
None,
"/@victim.example/path/chat",
),
(
"https://host.example.com\\some\\path",
"host.example.com",
"host.example.com",
"host.example.com",
None,
"/some/path/chat",
),
(
"https://host.example.com:8443\\v1\\foo",
"host.example.com:8443",
"host.example.com:8443",
"host.example.com",
Some(8443),
"/v1/foo/chat",
),
] {
let mut r = rig(
&[(script_host, Script::Answer(200, None, vec![b"ok"]))],
OnExhausted::Status503,
None,
);
r.egress
.routes
.get_mut(&DestinationId::new(1))
.expect("m0's route")
.base_url = base.to_string();
let t = token();
let far = r.egress.unit(route());
assert!(matches!(far.member(&t, 1).await, Pick::Member { .. }));
assert!(far.send(&t, request()).await, "{base}");
let pieces = drain(&far, &t).await;
assert_eq!(pieces[0].status, Some((200, 1)), "{base}");
drop(far);

let signed = r.auth.facts.lock().unwrap()[0].1.clone();
assert_eq!(signed, authority, "{base}: the signed host");
let opened = r.table.opened.lock().unwrap().clone();
assert_eq!(opened.len(), 1, "{base}");
let dialled =
busbar_contract::net::parse_url(&opened[0].0).unwrap_or_else(|e| panic!("{base}: {e}"));
assert_eq!(
(dialled.host.as_str(), dialled.port),
(host, port),
"{base}: the dialled host"
);
let dialled_authority = match dialled.port {
Some(p) => format!("{}:{p}", dialled.host),
None => dialled.host.clone(),
};
assert_eq!(
signed, dialled_authority,
"{base}: the signed host is the dialled host"
);
assert_eq!(
r.table.words.lock().unwrap()[0],
(b"POST".to_vec(), head_path.as_bytes().to_vec()),
"{base}: the head's path"
);
assert_eq!(
r.auth.facts.lock().unwrap()[0].2,
head_path.as_bytes().to_vec(),
"{base}: the signed path is the head's path"
);
}
}

/// An auth binding that must wait (a refresh that never comes back) is awaited no longer than the
/// attempt's cap: the attempt ends without a dial, nothing recorded against the member.
#[tokio::test]
Expand Down
91 changes: 91 additions & 0 deletions crates/busbar-kernel/src/plane_driver/tests/route_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,97 @@ fn a_node_without_signing_material_lends_no_caller_reference() {
assert!(i.caller_ref.ptr.is_null() && i.caller_ref.len == 0);
}

// ── F25 rows 630-633: rehomed from crates/busbar-llm/src/engine/tests/wire_tests.rs. The
// route-policy transparency pair as the pump stamps it
// (`route_policy_fields`, 1.5.5's `maybe_attach_route_policy_gated`), over the full 2x2 matrix of
// the outer (operator opt-in) and inner (a non-default policy chose) gates.

/// Both `x-busbar-route-*` fields the pump would stamp after the plane's own `fields` for
/// `(enabled, policy, member)`, as a `(policy, target)` pair (empty strings when absent); the
/// plane's own fields stay first and untouched.
fn built_route_fields(enabled: bool, policy: Option<&str>, member: &[u8]) -> (String, String) {
let mut fields: HeadFields = vec![(b"content-type".to_vec(), b"application/json".to_vec())];
route_policy_fields(&mut fields, enabled, policy, member);
assert_eq!(
fields[0],
(b"content-type".to_vec(), b"application/json".to_vec()),
"the plane's own fields lead"
);
let get = |name: &str| {
fields
.iter()
.find(|(n, _)| n.as_slice() == name.as_bytes())
.map(|(_, v)| String::from_utf8(v.clone()).expect("utf8"))
.unwrap_or_default()
};
(
get(crate::proxy::HDR_ROUTE_POLICY),
get(crate::proxy::HDR_ROUTE_TARGET),
)
}

/// F25 row 630: rehomed from crates/busbar-llm/src/engine/tests/wire_tests.rs::
/// route_policy_headers_suppressed_when_outer_gate_disabled_even_with_a_policy_name. Even with a
/// policy name present, the outer gate off suppresses BOTH fields.
#[test]
fn route_policy_headers_suppressed_when_outer_gate_disabled_even_with_a_policy_name() {
let (policy, target) = built_route_fields(false, Some("cheapest"), b"claude");
assert_eq!(
policy, "",
"route-policy header must be absent when the outer gate is off"
);
assert_eq!(
target, "",
"route-target header must be absent when the outer gate is off"
);
}

/// F25 row 631: rehomed from crates/busbar-llm/src/engine/tests/wire_tests.rs::
/// route_policy_headers_absent_for_a_default_policy_even_when_outer_gate_enabled. With the outer
/// gate ON, a default routing decision (no policy name) attaches nothing.
#[test]
fn route_policy_headers_absent_for_a_default_policy_even_when_outer_gate_enabled() {
let (policy, target) = built_route_fields(true, None, b"claude");
assert_eq!(
policy, "",
"no policy name -> no header, regardless of the outer gate"
);
assert_eq!(
target, "",
"no policy name -> no header, regardless of the outer gate"
);
}

/// F25 row 632: rehomed from crates/busbar-llm/src/engine/tests/wire_tests.rs::
/// route_policy_headers_present_only_when_both_gates_open. Both gates open is the only combination
/// that emits the pair, carrying the exact policy name and target member.
#[test]
fn route_policy_headers_present_only_when_both_gates_open() {
let (policy, target) = built_route_fields(true, Some("cheapest"), b"claude");
assert_eq!(policy, "cheapest");
assert_eq!(target, "claude");
let mut fields: HeadFields = Vec::new();
route_policy_fields(&mut fields, true, Some("cheapest"), b"claude");
assert_eq!(
fields,
vec![
(b"x-busbar-route-policy".to_vec(), b"cheapest".to_vec()),
(b"x-busbar-route-target".to_vec(), b"claude".to_vec()),
],
"exactly the pair, policy first"
);
}

/// F25 row 633: rehomed from crates/busbar-llm/src/engine/tests/wire_tests.rs::
/// route_policy_headers_absent_when_both_gates_closed. The fourth combination (outer off, inner off)
/// is also silent, completing the 2x2 matrix.
#[test]
fn route_policy_headers_absent_when_both_gates_closed() {
let (policy, target) = built_route_fields(false, None, b"claude");
assert_eq!(policy, "");
assert_eq!(target, "");
}

/// The reference the driver derives is the node's keyed digest of the principal, never the
/// principal: 64 lower-case hex characters that do not contain it.
#[test]
Expand Down