@@ -1160,6 +1160,119 @@ fn adapters_delegate_protocol_private_config_parsing_to_protocols() {
11601160 }
11611161}
11621162
1163+ #[test]
1164+ fn proxy_boundary_todo_completion_invariants_are_locked() {
1165+ for removed in [
1166+ "src/protocol_runtime",
1167+ "src/outbound",
1168+ "src/protocol_registry.rs",
1169+ ] {
1170+ assert!(
1171+ !manifest_dir().join(removed).exists(),
1172+ "legacy proxy dumping-ground path `{removed}` must not exist"
1173+ );
1174+ }
1175+
1176+ let runtime_roots = ["src/runtime", "src/runtime.rs"];
1177+ for runtime_root in runtime_roots {
1178+ let sources = if runtime_root.ends_with(".rs") {
1179+ vec![manifest_dir().join(runtime_root)]
1180+ } else {
1181+ rust_sources_under(runtime_root)
1182+ };
1183+ for path in sources {
1184+ let source = relative(&path);
1185+ let content = fs::read_to_string(&path).expect("read runtime source");
1186+ for forbidden in [
1187+ "InboundProtocolConfig::",
1188+ "OutboundProtocolConfig::",
1189+ "ResolvedLeafOutbound::",
1190+ "use socks5::",
1191+ "use vless::",
1192+ "use vmess::",
1193+ "use shadowsocks::",
1194+ "use trojan::",
1195+ "use hysteria2::",
1196+ "use mieru::",
1197+ ] {
1198+ assert!(
1199+ !content.contains(forbidden),
1200+ "{source} should remain protocol-neutral for the TODO boundary; found `{forbidden}`"
1201+ );
1202+ }
1203+ }
1204+ }
1205+
1206+ for path in rust_sources_under("src/adapters") {
1207+ let source = relative(&path);
1208+ let content = fs::read_to_string(&path).expect("read adapter source");
1209+ for forbidden in [
1210+ "parse_uuid",
1211+ "parse_flow",
1212+ "Uuid::parse",
1213+ "VmessCipher::from_name",
1214+ "CipherKind::from_str",
1215+ "sha224",
1216+ "blake3",
1217+ "encrypt_packet",
1218+ "decrypt_packet",
1219+ "encode_udp_packet",
1220+ "decode_udp_packet",
1221+ ] {
1222+ assert!(
1223+ !content.contains(forbidden),
1224+ "{source} should stay a thin adapter bridge and delegate protocol-private parsing/framing; found `{forbidden}`"
1225+ );
1226+ }
1227+ }
1228+
1229+ for source in [
1230+ "src/inbound/datagram_udp.rs",
1231+ "src/inbound/stream_udp.rs",
1232+ "src/inbound/mux_udp.rs",
1233+ ] {
1234+ let content = read(source);
1235+ for forbidden in [
1236+ "read_buf",
1237+ "pending_dispatch",
1238+ "client_map",
1239+ "client_sessions",
1240+ "CipherKind",
1241+ "password: &str",
1242+ "Codec::new",
1243+ "decode_udp_packet",
1244+ "encode_udp_packet",
1245+ "ResponseTarget",
1246+ ] {
1247+ assert!(
1248+ !content.contains(forbidden),
1249+ "{source} should stay shared inbound UDP orchestration glue, not protocol-private state; found `{forbidden}`"
1250+ );
1251+ }
1252+ }
1253+
1254+ let architecture = fs::read_to_string(repo_root().join("docs/project/architecture.md"))
1255+ .expect("read docs/project/architecture.md");
1256+ let agents = fs::read_to_string(repo_root().join("AGENTS.md")).expect("read AGENTS.md");
1257+ for (path, content) in [
1258+ ("docs/project/architecture.md", architecture.as_str()),
1259+ ("AGENTS.md", agents.as_str()),
1260+ ] {
1261+ for forbidden in [
1262+ "Protocol identity and cipher config parsing is adapter-owned",
1263+ "protocol's own adapter",
1264+ "move protocol state to src/protocol_runtime",
1265+ "proxy owns response bridge",
1266+ "代理拥有传输设置、socket 设置、路由、会话生命周期、统计、事件和响应桥接",
1267+ ] {
1268+ assert!(
1269+ !content.contains(forbidden),
1270+ "{path} should describe the converged proxy/protocol boundary, not stale TODO-era ownership `{forbidden}`"
1271+ );
1272+ }
1273+ }
1274+ }
1275+
11631276#[test]
11641277fn runtime_does_not_match_protocol_config_variants() {
11651278 for path in rust_sources_under("src/runtime") {
0 commit comments