From 132915a4e5b9df9bfa721cd06c5da2a0e7b8359b Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Fri, 17 Jul 2026 10:53:36 +0200 Subject: [PATCH] test(engine): browse-inclusive union-frame rejection cases (PR #184 review) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hoshe's finding: the H1 union-rejection mechanism correctly counts the new browse discriminator, but ambiguous_union_frame_is_rejected was carried over from PR #176 without a browse-inclusive case — a future demux/ShapeProbe refactor could drop the fifth shape from the union check with nothing to catch it. Adds browse+star_map and browse+city_names union frames, both asserting rejection. Co-Authored-By: Claude Fable 5 --- server/src/bridge/mod.rs | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/server/src/bridge/mod.rs b/server/src/bridge/mod.rs index 6a17eabd9..e9d276944 100644 --- a/server/src/bridge/mod.rs +++ b/server/src/bridge/mod.rs @@ -1316,5 +1316,51 @@ mod inbound_tests { decode_inbound(&frame).is_err(), "atlas+star_map union frame must be rejected" ); + + // T-1131 (PR #184 review): the FIFTH shape's discriminator (`browse`) + // must participate in the same union rejection — a well-formed + // BrowseRequest smuggling another shape's discriminator alongside it + // is rejected, not routed to whichever probe wins. + #[derive(serde::Serialize)] + struct BrowseAndStar { + browse: bool, + kind: crate::atlas::browse_proxy::BrowseEntityKind, + query: crate::atlas::browse_proxy::BrowseQuery, + star_map: bool, + } + let frame = rmp_serde::to_vec_named(&BrowseAndStar { + browse: true, + kind: crate::atlas::browse_proxy::BrowseEntityKind::StarSystem, + query: crate::atlas::browse_proxy::BrowseQuery::Index { + filter_system_id: None, + }, + star_map: true, + }) + .unwrap(); + assert!( + decode_inbound(&frame).is_err(), + "browse+star_map union frame must be rejected" + ); + + #[derive(serde::Serialize)] + struct BrowseAndCity { + browse: bool, + kind: crate::atlas::browse_proxy::BrowseEntityKind, + query: crate::atlas::browse_proxy::BrowseQuery, + city_names: bool, + body_id: String, + } + let frame = rmp_serde::to_vec_named(&BrowseAndCity { + browse: true, + kind: crate::atlas::browse_proxy::BrowseEntityKind::Body, + query: crate::atlas::browse_proxy::BrowseQuery::Detail { id: "GJ1c".into() }, + city_names: true, + body_id: "GJ1c".into(), + }) + .unwrap(); + assert!( + decode_inbound(&frame).is_err(), + "browse+city_names union frame must be rejected" + ); } }