gameplay: compose complete connect caller policy
Browse files- crates/urt-gameplay/src/bin/urt-native-policy.rs +149 -0
- crates/urt-gameplay/src/native_policy.rs +172 -0
- docs/FINDINGS.md +3 -0
- docs/PROVISIONAL_TODO.md +6 -0
- docs/RESEARCH_LEDGER.md +10 -0
- docs/REVERSE_ENGINEERING_TODO.md +7 -1
- docs/TESTING.md +3 -0
- docs/research/QVM_CONNECT_POLICY_BATCH.md +55 -0
- docs/research/QVM_SESSION_LIFECYCLE_BATCH.md +3 -1
- docs/research/README.md +6 -0
- docs/research/RUST_CONNECT_COMPLETE.md +7 -0
- docs/research/rust-connect-complete.json +0 -0
- docs/research/rust-health-impulse.json +1 -1
- scripts/analyze_rust_connect_complete.py +15 -0
- scripts/test_rust_connect_complete.py +9 -0
- xtask/checks.tsv +15 -0
- xtask/src/lib.rs +11 -0
crates/urt-gameplay/src/bin/urt-native-policy.rs
CHANGED
|
@@ -873,6 +873,92 @@ fn run() -> Result<String, String> {
|
|
| 873 |
.map_err(|e| format!("{e:?}"))?;
|
| 874 |
Ok(tail_json(&out, &client, &entity))
|
| 875 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 876 |
_ => Err("unknown command".into()),
|
| 877 |
}
|
| 878 |
}
|
|
@@ -1258,3 +1344,66 @@ fn tail_json(out: &ConnectTail, client: &[u8], entity: &ConnectTailEntity) -> St
|
|
| 1258 |
out.ring_advance
|
| 1259 |
)
|
| 1260 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 873 |
.map_err(|e| format!("{e:?}"))?;
|
| 874 |
Ok(tail_json(&out, &client, &entity))
|
| 875 |
}
|
| 876 |
+
"connect-complete" => {
|
| 877 |
+
if w.len() < 9 {
|
| 878 |
+
return Err("missing complete header".into());
|
| 879 |
+
}
|
| 880 |
+
let n = w[8] as usize;
|
| 881 |
+
if n > 1024 || w.len() < 9 + 2 * n {
|
| 882 |
+
return Err("invalid complete table".into());
|
| 883 |
+
}
|
| 884 |
+
let entries = w[9..9 + 2 * n]
|
| 885 |
+
.chunks_exact(2)
|
| 886 |
+
.map(|v| (v[0], v[1]))
|
| 887 |
+
.collect::<Vec<_>>();
|
| 888 |
+
let mut p = 9 + 2 * n;
|
| 889 |
+
let info = input_blob(&w, &mut p)?.ok_or("null complete info")?;
|
| 890 |
+
let password = input_blob(&w, &mut p)?.ok_or("null complete password")?;
|
| 891 |
+
if p != w.len() {
|
| 892 |
+
return Err("trailing complete words".into());
|
| 893 |
+
}
|
| 894 |
+
let mut client = 0xaabbccddu32.to_le_bytes().repeat(1584);
|
| 895 |
+
client[504..516].fill(0);
|
| 896 |
+
client[504..507].copy_from_slice(b"old");
|
| 897 |
+
let mut entity = CompleteConnectEntity {
|
| 898 |
+
session: ConnectEntity {
|
| 899 |
+
linked_slot: None,
|
| 900 |
+
field764: 0xaabbccdd,
|
| 901 |
+
field768: 0xaabbccdd,
|
| 902 |
+
},
|
| 903 |
+
tail: ConnectTailEntity {
|
| 904 |
+
flags: 32,
|
| 905 |
+
in_use: 0,
|
| 906 |
+
},
|
| 907 |
+
};
|
| 908 |
+
let mut ring = 0;
|
| 909 |
+
let out = complete_connect(
|
| 910 |
+
&mut client,
|
| 911 |
+
&mut entity,
|
| 912 |
+
CompleteConnectInput {
|
| 913 |
+
admission: AdmissionInput {
|
| 914 |
+
slot: 3,
|
| 915 |
+
bot: w[3] as i32,
|
| 916 |
+
userinfo: &info,
|
| 917 |
+
password: &password,
|
| 918 |
+
entries: &entries,
|
| 919 |
+
count: n as i32,
|
| 920 |
+
mode: 1,
|
| 921 |
+
scratch: w[6],
|
| 922 |
+
},
|
| 923 |
+
first_time: w[1] as i32,
|
| 924 |
+
new_session: w[2] as i32,
|
| 925 |
+
flags: 1,
|
| 926 |
+
initialize: InitializeInput {
|
| 927 |
+
mode: w[0] as i32,
|
| 928 |
+
slot: 3,
|
| 929 |
+
userinfo: &info,
|
| 930 |
+
limit: 2,
|
| 931 |
+
occupancy: 1,
|
| 932 |
+
seconds: 0,
|
| 933 |
+
clock: 100,
|
| 934 |
+
ticks: 17,
|
| 935 |
+
handle: 7,
|
| 936 |
+
client_id: 0,
|
| 937 |
+
enabled: 1,
|
| 938 |
+
mapname: b"ut4_test",
|
| 939 |
+
file_length: 11,
|
| 940 |
+
file_data: b"9,8,7,6,5,4",
|
| 941 |
+
},
|
| 942 |
+
session: b"1,-2,3,4,5,1,1,1,1",
|
| 943 |
+
ignore_text: b"1,3,",
|
| 944 |
+
scratch: [w[5]; 5],
|
| 945 |
+
tail: ConnectTailInput {
|
| 946 |
+
mode: w[0] as i32,
|
| 947 |
+
slot: 3,
|
| 948 |
+
first_time: w[1] as i32,
|
| 949 |
+
bot: w[3] as i32,
|
| 950 |
+
bot_answer: w[4] as i32,
|
| 951 |
+
clock: 100,
|
| 952 |
+
seconds: 0,
|
| 953 |
+
after_team: if w[7] != 0 { Some(2) } else { None },
|
| 954 |
+
name: b"new^1name",
|
| 955 |
+
},
|
| 956 |
+
},
|
| 957 |
+
&mut ring,
|
| 958 |
+
)
|
| 959 |
+
.map_err(|e| format!("{e:?}"))?;
|
| 960 |
+
Ok(complete_json(&out, &client, &entity, ring))
|
| 961 |
+
}
|
| 962 |
_ => Err("unknown command".into()),
|
| 963 |
}
|
| 964 |
}
|
|
|
|
| 1344 |
out.ring_advance
|
| 1345 |
)
|
| 1346 |
}
|
| 1347 |
+
|
| 1348 |
+
fn complete_json(
|
| 1349 |
+
out: &CompleteConnect,
|
| 1350 |
+
client: &[u8],
|
| 1351 |
+
entity: &CompleteConnectEntity,
|
| 1352 |
+
ring: u32,
|
| 1353 |
+
) -> String {
|
| 1354 |
+
let message = out
|
| 1355 |
+
.message
|
| 1356 |
+
.as_ref()
|
| 1357 |
+
.map(|v| format!(r#""{}""#, hex(v)))
|
| 1358 |
+
.unwrap_or("null".into());
|
| 1359 |
+
let steps = out
|
| 1360 |
+
.admission
|
| 1361 |
+
.steps
|
| 1362 |
+
.iter()
|
| 1363 |
+
.map(|v| format!(r#""{v}""#))
|
| 1364 |
+
.collect::<Vec<_>>()
|
| 1365 |
+
.join(",");
|
| 1366 |
+
let filter = out
|
| 1367 |
+
.admission
|
| 1368 |
+
.filter
|
| 1369 |
+
.as_ref()
|
| 1370 |
+
.map(|f| {
|
| 1371 |
+
format!(
|
| 1372 |
+
r#"{{"filter_result":{},"parsed":{}}}"#,
|
| 1373 |
+
u32::from(f.rejected),
|
| 1374 |
+
f.parsed.map(|v| v.to_string()).unwrap_or("null".into())
|
| 1375 |
+
)
|
| 1376 |
+
})
|
| 1377 |
+
.unwrap_or("{}".into());
|
| 1378 |
+
let (choice, sets, reads) = if let Some(life) = &out.lifecycle {
|
| 1379 |
+
(
|
| 1380 |
+
format!("[{}]", if life.fresh { 247520 } else { 247219 }),
|
| 1381 |
+
life.initialized
|
| 1382 |
+
.as_ref()
|
| 1383 |
+
.map(|v| sets_json(&v.session.sets))
|
| 1384 |
+
.unwrap_or("[]".into()),
|
| 1385 |
+
life.restored
|
| 1386 |
+
.as_ref()
|
| 1387 |
+
.map(|v| sets_json(&v.cvars))
|
| 1388 |
+
.unwrap_or("[]".into()),
|
| 1389 |
+
)
|
| 1390 |
+
} else {
|
| 1391 |
+
("[]".into(), "[]".into(), "[]".into())
|
| 1392 |
+
};
|
| 1393 |
+
let checksum = client.iter().fold(14695981039346656037u64, |v, b| {
|
| 1394 |
+
(v ^ *b as u64).wrapping_mul(1099511628211)
|
| 1395 |
+
});
|
| 1396 |
+
format!(
|
| 1397 |
+
r#"{{"accepted":{},"message":{message},"steps":[{steps}],"filter":{filter},"events":{},"choice":{choice},"raw":"{}","client_checksum":{checksum},"words":{},"entity":[{},{},{},{},{}],"sets":{sets},"reads":{reads},"ring":{},"info_ring":{ring}}}"#,
|
| 1398 |
+
out.accepted,
|
| 1399 |
+
tail_events(&out.events),
|
| 1400 |
+
hex(&client[3096..4040]),
|
| 1401 |
+
watched_words(client),
|
| 1402 |
+
entity.tail.flags,
|
| 1403 |
+
entity.tail.in_use as u32,
|
| 1404 |
+
entity.session.field764,
|
| 1405 |
+
entity.session.field768,
|
| 1406 |
+
u32::from(entity.session.linked_slot == Some(3)),
|
| 1407 |
+
out.ring_advance
|
| 1408 |
+
)
|
| 1409 |
+
}
|
crates/urt-gameplay/src/native_policy.rs
CHANGED
|
@@ -2515,3 +2515,175 @@ mod connect_tail_tests {
|
|
| 2515 |
assert_eq!(raw_word(&raw, 3140), 100);
|
| 2516 |
}
|
| 2517 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2515 |
assert_eq!(raw_word(&raw, 3140), 100);
|
| 2516 |
}
|
| 2517 |
}
|
| 2518 |
+
|
| 2519 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 2520 |
+
pub struct CompleteConnectEntity {
|
| 2521 |
+
pub session: ConnectEntity,
|
| 2522 |
+
pub tail: ConnectTailEntity,
|
| 2523 |
+
}
|
| 2524 |
+
pub struct CompleteConnectInput<'a> {
|
| 2525 |
+
pub admission: AdmissionInput<'a>,
|
| 2526 |
+
pub first_time: i32,
|
| 2527 |
+
pub new_session: i32,
|
| 2528 |
+
pub flags: u32,
|
| 2529 |
+
pub initialize: InitializeInput<'a>,
|
| 2530 |
+
pub session: &'a [u8],
|
| 2531 |
+
pub ignore_text: &'a [u8],
|
| 2532 |
+
pub scratch: [u32; 5],
|
| 2533 |
+
pub tail: ConnectTailInput<'a>,
|
| 2534 |
+
}
|
| 2535 |
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
| 2536 |
+
pub struct CompleteConnect {
|
| 2537 |
+
pub admission: Admission,
|
| 2538 |
+
pub lifecycle: Option<ConnectedSession>,
|
| 2539 |
+
pub tail: Option<ConnectTail>,
|
| 2540 |
+
pub accepted: bool,
|
| 2541 |
+
pub message: Option<Vec<u8>>,
|
| 2542 |
+
pub events: Vec<ConnectTailEvent>,
|
| 2543 |
+
pub ring_advance: u32,
|
| 2544 |
+
}
|
| 2545 |
+
/// Compose the complete173979 policy. Ordinary denial is a source return, not
|
| 2546 |
+
/// a typed error: auth denial changes only the selector; bot denial keeps prior
|
| 2547 |
+
/// lifecycle/entity changes. Unsupported domains stage all state atomically.
|
| 2548 |
+
pub fn complete_connect(
|
| 2549 |
+
client: &mut [u8],
|
| 2550 |
+
entity: &mut CompleteConnectEntity,
|
| 2551 |
+
input: CompleteConnectInput<'_>,
|
| 2552 |
+
info_ring: &mut u32,
|
| 2553 |
+
) -> Result<CompleteConnect, Error> {
|
| 2554 |
+
if client.len() != CLIENT_BYTES
|
| 2555 |
+
|| input.admission.slot != input.initialize.slot
|
| 2556 |
+
|| input.tail.slot != input.initialize.slot
|
| 2557 |
+
|| input.tail.mode != input.initialize.mode
|
| 2558 |
+
|| input.tail.first_time != input.first_time
|
| 2559 |
+
|| input.tail.bot != input.admission.bot
|
| 2560 |
+
{
|
| 2561 |
+
return Err(Error::InvalidInput);
|
| 2562 |
+
}
|
| 2563 |
+
let mut selector = *info_ring;
|
| 2564 |
+
let admission = admit_connect(input.admission, &mut selector)?;
|
| 2565 |
+
if !admission.accepted {
|
| 2566 |
+
let message = admission.message.clone();
|
| 2567 |
+
*info_ring = selector;
|
| 2568 |
+
return Ok(CompleteConnect {
|
| 2569 |
+
admission,
|
| 2570 |
+
lifecycle: None,
|
| 2571 |
+
tail: None,
|
| 2572 |
+
accepted: false,
|
| 2573 |
+
message,
|
| 2574 |
+
events: vec![],
|
| 2575 |
+
ring_advance: 0,
|
| 2576 |
+
});
|
| 2577 |
+
}
|
| 2578 |
+
let mut bytes = client.to_vec();
|
| 2579 |
+
let mut e = entity.clone();
|
| 2580 |
+
let lifecycle = connect_session(
|
| 2581 |
+
&mut bytes,
|
| 2582 |
+
&mut e.session,
|
| 2583 |
+
ConnectInput {
|
| 2584 |
+
first_time: input.first_time,
|
| 2585 |
+
new_session: input.new_session,
|
| 2586 |
+
flags: input.flags,
|
| 2587 |
+
initialize: input.initialize,
|
| 2588 |
+
session: input.session,
|
| 2589 |
+
ignore_text: input.ignore_text,
|
| 2590 |
+
scratch: input.scratch,
|
| 2591 |
+
},
|
| 2592 |
+
&mut selector,
|
| 2593 |
+
)?;
|
| 2594 |
+
let tail = finish_connect(&mut bytes, &mut e.tail, input.tail)?;
|
| 2595 |
+
let accepted = tail.accepted;
|
| 2596 |
+
let message = tail.message.clone();
|
| 2597 |
+
let mut events = vec![ConnectTailEvent::Zero {
|
| 2598 |
+
offset: 0,
|
| 2599 |
+
length: CLIENT_BYTES,
|
| 2600 |
+
}];
|
| 2601 |
+
events.extend(tail.events.clone());
|
| 2602 |
+
let ring_advance = lifecycle.ring_advance + tail.ring_advance;
|
| 2603 |
+
client.copy_from_slice(&bytes);
|
| 2604 |
+
*entity = e;
|
| 2605 |
+
*info_ring = selector;
|
| 2606 |
+
Ok(CompleteConnect {
|
| 2607 |
+
admission,
|
| 2608 |
+
lifecycle: Some(lifecycle),
|
| 2609 |
+
tail: Some(tail),
|
| 2610 |
+
accepted,
|
| 2611 |
+
message,
|
| 2612 |
+
events,
|
| 2613 |
+
ring_advance,
|
| 2614 |
+
})
|
| 2615 |
+
}
|
| 2616 |
+
#[cfg(test)]
|
| 2617 |
+
mod complete_connect_tests {
|
| 2618 |
+
use super::*;
|
| 2619 |
+
#[test]
|
| 2620 |
+
fn invalid_record_is_atomic_before_admission() {
|
| 2621 |
+
let mut bytes = [];
|
| 2622 |
+
let mut entity = CompleteConnectEntity {
|
| 2623 |
+
session: ConnectEntity {
|
| 2624 |
+
linked_slot: None,
|
| 2625 |
+
field764: 7,
|
| 2626 |
+
field768: 8,
|
| 2627 |
+
},
|
| 2628 |
+
tail: ConnectTailEntity {
|
| 2629 |
+
flags: 32,
|
| 2630 |
+
in_use: 0,
|
| 2631 |
+
},
|
| 2632 |
+
};
|
| 2633 |
+
let before = entity.clone();
|
| 2634 |
+
let mut ring = 0;
|
| 2635 |
+
let result = complete_connect(
|
| 2636 |
+
&mut bytes,
|
| 2637 |
+
&mut entity,
|
| 2638 |
+
CompleteConnectInput {
|
| 2639 |
+
admission: AdmissionInput {
|
| 2640 |
+
slot: 0,
|
| 2641 |
+
bot: 0,
|
| 2642 |
+
userinfo: b"",
|
| 2643 |
+
password: b"",
|
| 2644 |
+
entries: &[],
|
| 2645 |
+
count: 0,
|
| 2646 |
+
mode: 1,
|
| 2647 |
+
scratch: 0,
|
| 2648 |
+
},
|
| 2649 |
+
first_time: 0,
|
| 2650 |
+
new_session: 0,
|
| 2651 |
+
flags: 0,
|
| 2652 |
+
initialize: InitializeInput {
|
| 2653 |
+
mode: 0,
|
| 2654 |
+
slot: 0,
|
| 2655 |
+
userinfo: b"",
|
| 2656 |
+
limit: 0,
|
| 2657 |
+
occupancy: 0,
|
| 2658 |
+
seconds: 0,
|
| 2659 |
+
clock: 0,
|
| 2660 |
+
ticks: 0,
|
| 2661 |
+
handle: 0,
|
| 2662 |
+
client_id: 0,
|
| 2663 |
+
enabled: 0,
|
| 2664 |
+
mapname: b"m",
|
| 2665 |
+
file_length: 0,
|
| 2666 |
+
file_data: b"",
|
| 2667 |
+
},
|
| 2668 |
+
session: b"",
|
| 2669 |
+
ignore_text: b"",
|
| 2670 |
+
scratch: [0; 5],
|
| 2671 |
+
tail: ConnectTailInput {
|
| 2672 |
+
mode: 0,
|
| 2673 |
+
slot: 0,
|
| 2674 |
+
first_time: 0,
|
| 2675 |
+
bot: 0,
|
| 2676 |
+
bot_answer: 1,
|
| 2677 |
+
clock: 0,
|
| 2678 |
+
seconds: 0,
|
| 2679 |
+
after_team: None,
|
| 2680 |
+
name: b"n",
|
| 2681 |
+
},
|
| 2682 |
+
},
|
| 2683 |
+
&mut ring,
|
| 2684 |
+
);
|
| 2685 |
+
assert_eq!(result, Err(Error::InvalidInput));
|
| 2686 |
+
assert_eq!(entity, before);
|
| 2687 |
+
assert_eq!(ring, 0);
|
| 2688 |
+
}
|
| 2689 |
+
}
|
docs/FINDINGS.md
CHANGED
|
@@ -1766,3 +1766,6 @@ RE-813–822 replaces the scoreboard decimal assumption with actual37914 executi
|
|
| 1766 |
|
| 1767 |
|
| 1768 |
**RE-922:** 96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. [Evidence](research/QVM_CONNECT_COMPLETE.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 1766 |
|
| 1767 |
|
| 1768 |
**RE-922:** 96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. [Evidence](research/QVM_CONNECT_COMPLETE.md).
|
| 1769 |
+
|
| 1770 |
+
|
| 1771 |
+
**RE-923:** Rust matches96 complete173979 executions across admission, client clear, initialization/restore, bot admission and callback completion. Auth denial preserves client/entity state; bot denial retains lifecycle effects. Source messages, cvar timing, full-client checksums, raw watched bytes and selector/formatter carry match. Native callback bodies, actual network/IO acceptance and runtime integration remain open. [Evidence](research/RUST_CONNECT_COMPLETE.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -1806,3 +1806,9 @@ RE-921: Rust matches144 original173979 suffix cases with ordered bot admission,
|
|
| 1806 |
|
| 1807 |
|
| 1808 |
RE-922: 96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_COMPLETE.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1806 |
|
| 1807 |
|
| 1808 |
RE-922: 96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. Full runtime completion remains open. [Evidence](research/QVM_CONNECT_COMPLETE.md).
|
| 1809 |
+
|
| 1810 |
+
|
| 1811 |
+
RE-923: Rust matches96 complete173979 executions across admission, client clear, initialization/restore, bot admission and callback completion. Auth denial preserves client/entity state; bot denial retains lifecycle effects. Source messages, cvar timing, full-client checksums, raw watched bytes and selector/formatter carry match. Native callback bodies, actual network/IO acceptance and runtime integration remain open. Full runtime completion remains open. [Evidence](research/RUST_CONNECT_COMPLETE.md).
|
| 1812 |
+
|
| 1813 |
+
|
| 1814 |
+
RE-914–923 completed bounded comparison/filter/admission/completion and whole173979 caller composition. RE-924 tracks concrete callback bodies, filter writers, native engine ownership and full runtime integration. [Batch and next work](research/QVM_CONNECT_POLICY_BATCH.md).
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -2335,3 +2335,13 @@ Rust matches144 original173979 suffix cases with ordered bot admission, first-ti
|
|
| 2335 |
## 2026-10-28 — RE-922 Complete original connect caller with recovered admission/lifecycle/tail
|
| 2336 |
|
| 2337 |
96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. Focused `cargo xtask test-group qvm-connect-complete` passes (13 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2335 |
## 2026-10-28 — RE-922 Complete original connect caller with recovered admission/lifecycle/tail
|
| 2336 |
|
| 2337 |
96 complete173979 executions compose actual userinfo/address/password admission, native client-clear boundary,247520 initialization or247219 restore, team normalization and bot/callback completion. Ordinary authentication rejection preserves client/entity state; bot rejection occurs after lifecycle side effects. Initializer-persisted timeout can precede a first-time overwrite. Client-wide checksums, watched bytes, exact messages, cvar order and selector/formatter carry are verified. Native admission/userinfo/team/ranking/IO/network callbacks remain supplied/captured; this is not native multiplayer acceptance. Focused `cargo xtask test-group qvm-connect-complete` passes (13 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
| 2338 |
+
|
| 2339 |
+
|
| 2340 |
+
## 2026-10-28 — RE-923 Rust complete connect policy composition
|
| 2341 |
+
|
| 2342 |
+
Rust matches96 complete173979 executions across admission, client clear, initialization/restore, bot admission and callback completion. Auth denial preserves client/entity state; bot denial retains lifecycle effects. Source messages, cvar timing, full-client checksums, raw watched bytes and selector/formatter carry match. Native callback bodies, actual network/IO acceptance and runtime integration remain open. Focused `cargo xtask test-group rust-connect-complete` passes (9 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
|
| 2343 |
+
|
| 2344 |
+
|
| 2345 |
+
### RE-914–923 full batch validation (2026-10-28)
|
| 2346 |
+
|
| 2347 |
+
After the tenth commit, `cargo xtask test-full --since 2b1ac7ec` passed on its first full attempt with the flake-declared Nix Python: 1,783 Python tests,216 Rust tests (assets10, gameplay176, xtask30),32 affected report producers regenerated twice deterministically, storage policy,491 documentation link checks and whitespace guards. No generated-report drift. Ten task commits since2b1ac7ec; validation notes are amended into the tenth commit. [Findings and next work](research/QVM_CONNECT_POLICY_BATCH.md).
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -1815,7 +1815,7 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1815 |
- [x] RE-913 Rust connect clear and session lifecycle branch ([evidence](research/RUST_CONNECT_SESSION.md)).
|
| 1816 |
|
| 1817 |
|
| 1818 |
-
- [ ] RE-
|
| 1819 |
|
| 1820 |
|
| 1821 |
- [x] RE-914 Original unsigned byte string comparison ([evidence](research/QVM_BYTE_COMPARE.md)).
|
|
@@ -1843,3 +1843,9 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 1843 |
|
| 1844 |
|
| 1845 |
- [x] RE-922 Complete original connect caller with recovered admission/lifecycle/tail ([evidence](research/QVM_CONNECT_COMPLETE.md)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1815 |
- [x] RE-913 Rust connect clear and session lifecycle branch ([evidence](research/RUST_CONNECT_SESSION.md)).
|
| 1816 |
|
| 1817 |
|
| 1818 |
+
- [ ] Follow-up after RE-913: complete connect authentication/normalization, native IO/reload, scanner/alias domains and full runtime integration ([next work](research/QVM_SESSION_LIFECYCLE_BATCH.md)).
|
| 1819 |
|
| 1820 |
|
| 1821 |
- [x] RE-914 Original unsigned byte string comparison ([evidence](research/QVM_BYTE_COMPARE.md)).
|
|
|
|
| 1843 |
|
| 1844 |
|
| 1845 |
- [x] RE-922 Complete original connect caller with recovered admission/lifecycle/tail ([evidence](research/QVM_CONNECT_COMPLETE.md)).
|
| 1846 |
+
|
| 1847 |
+
|
| 1848 |
+
- [x] RE-923 Rust complete connect policy composition ([evidence](research/RUST_CONNECT_COMPLETE.md)).
|
| 1849 |
+
|
| 1850 |
+
|
| 1851 |
+
- [ ] RE-924 Recover bot/userinfo/team/ranking callback bodies, filter writers and native engine acceptance, with remaining scalar/alias and full runtime integration ([next work](research/QVM_CONNECT_POLICY_BATCH.md)).
|
docs/TESTING.md
CHANGED
|
@@ -169,3 +169,6 @@ RE-894–903 adds focused groups `qvm-info-lookup`, `rust-info-lookup`, `qvm-num
|
|
| 169 |
|
| 170 |
|
| 171 |
RE-904–913 adds focused groups `qvm-session-init`, `rust-session-init`, `qvm-post-map-files`, `rust-post-map-files`, `qvm-normal-map-files`, `rust-normal-map-files`, `qvm-persistence-roundtrip`, `rust-persistence-roundtrip`, `qvm-connect-session` and `rust-connect-session`. Invoke one group per command. The full suite after task ten uses `cargo xtask test-full --since 6d0ce63f` with explicit flake-declared Nix PYTHON. [Bounded lifecycle evidence](research/QVM_SESSION_LIFECYCLE_BATCH.md).
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
|
| 171 |
RE-904–913 adds focused groups `qvm-session-init`, `rust-session-init`, `qvm-post-map-files`, `rust-post-map-files`, `qvm-normal-map-files`, `rust-normal-map-files`, `qvm-persistence-roundtrip`, `rust-persistence-roundtrip`, `qvm-connect-session` and `rust-connect-session`. Invoke one group per command. The full suite after task ten uses `cargo xtask test-full --since 6d0ce63f` with explicit flake-declared Nix PYTHON. [Bounded lifecycle evidence](research/QVM_SESSION_LIFECYCLE_BATCH.md).
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
RE-914–923 adds `qvm-byte-compare`, `rust-byte-compare`, `qvm-address-filter`, `rust-address-filter`, `qvm-connect-admission`, `rust-connect-admission`, `qvm-connect-tail`, `rust-connect-tail`, `qvm-connect-complete` and `rust-connect-complete`. Invoke one group per command. Full validation after task ten uses `cargo xtask test-full --since 2b1ac7ec` with explicit flake-declared Nix PYTHON. [Bounded connect evidence](research/QVM_CONNECT_POLICY_BATCH.md).
|
docs/research/QVM_CONNECT_POLICY_BATCH.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Complete connect caller policy: RE-914–923
|
| 2 |
+
|
| 3 |
+
Ten separately committed tasks recover admission and completion policies and compose the entire original173979 QVM caller across926 paired source/Rust cases. The caller body executes, while bot admission, userinfo changes, team joining, ranking, engine buffers, files, logging and network sends remain supplied/captured boundaries. These finite policies do not establish native multiplayer acceptance or a complete playable game.
|
| 4 |
+
|
| 5 |
+
| Task | Evidence | Cases |
|
| 6 |
+
| --- | --- | ---: |
|
| 7 |
+
| RE-914 | [Unsigned36306 comparison](QVM_BYTE_COMPARE.md) | 256 |
|
| 8 |
+
| RE-915 | [Rust exact byte comparison](RUST_BYTE_COMPARE.md) | 256 |
|
| 9 |
+
| RE-916 | [Address252643 parsing/filtering](QVM_ADDRESS_FILTER.md) | 270 |
|
| 10 |
+
| RE-917 | [Rust address/scratch policy](RUST_ADDRESS_FILTER.md) | 270 |
|
| 11 |
+
| RE-918 | [173979 admission prefix](QVM_CONNECT_ADMISSION.md) | 160 |
|
| 12 |
+
| RE-919 | [Rust admission order](RUST_CONNECT_ADMISSION.md) | 160 |
|
| 13 |
+
| RE-920 | [173979 completion suffix](QVM_CONNECT_TAIL.md) | 144 |
|
| 14 |
+
| RE-921 | [Rust completion policy](RUST_CONNECT_TAIL.md) | 144 |
|
| 15 |
+
| RE-922 | [Complete173979 caller](QVM_CONNECT_COMPLETE.md) | 96 |
|
| 16 |
+
| RE-923 | [Rust complete caller composition](RUST_CONNECT_COMPLETE.md) | 96 |
|
| 17 |
+
|
| 18 |
+
## Strings, addresses and admission
|
| 19 |
+
|
| 20 |
+
Actual36306 compares words but returns the unsigned-byte difference at the first differing character. It is case-sensitive, terminates at NUL and is distinct from the previously recovered69386 case-folded comparison. Fixtures cover four pointer alignments, embedded NUL, case and high-byte differences. Guard bytes are explicit fixture memory; arbitrary pointer validity/aliases remain open.
|
| 21 |
+
|
| 22 |
+
Actual252643 first compares the input with exact lowercase localhost and bypasses filtering on that match. Otherwise it constructs up to four bytes at a caller-stack word. Each numeric component wraps modulo256; any single non-digit separator advances the component index, while colon or NUL ends parsing. Short/empty strings leave explicitly supplied prior bytes in untouched components. Thus this body is not strict IP validation. The result is a little-endian word tested against mask/value entries at36275952/36275956 with stride12 and signed count36275948. Nonzero34082796 returns true on a match; zero mode returns true on a miss. Negative counts skip scanning. Table population, raw network provenance and actual scratch provenance remain open.
|
| 23 |
+
|
| 24 |
+
The173979 prefix fetches userinfo first. A nonzero bot argument bypasses both address and password checks. Other clients look up ip, invoke the actual filter and return exact Banned. text before any password lookup when rejected. If permitted, password is looked up even when the server password is empty. Nonempty server passwords are compared case-insensitively with none; other values invoke exact36306 comparison against the supplied password. Mismatch returns Invalid password. Rejection precedes entity/client initialization. Userinfo buffer selectors carry in the actual lookup order.
|
| 25 |
+
|
| 26 |
+
## Completion ordering and partial rejection state
|
| 27 |
+
|
| 28 |
+
After the recovered initialize/restore branch, the caller normalizes team3096: team-classified modes replace zero with3; other modes replace values other than3 with0. Bot paths then set entity flag8 and in-use1 before requesting161744 with restart=!firstTime. A zero supplied result returns exact BotConnectfailed text after those mutations. The Rust policy preserves that ordinary rejection state; typed unsupported-domain errors stage state instead.
|
| 29 |
+
|
| 30 |
+
Successful first-time paths clear client668..695 and compute timeout3140 as clock+seconds*1000, with no initializer60-second default. They log, clear3588 and the3204..3587 message regions, then request171668 userinfo processing. Fixtures supply the resulting team/name changes. The first-time connection announcement uses that updated name and exact original70458/37914 formatting: the logical native command includes its print wrapper, quotes and newline. The Rust boundary removes the formatter's terminating NUL from its logical command bytes. A second team classification/decision observes the updated team, optionally requests182896 with choice-1, and5864 ranking is requested last. Native callback bodies and their arbitrary global effects remain open.
|
| 31 |
+
|
| 32 |
+
## Whole caller composition
|
| 33 |
+
|
| 34 |
+
The96 complete original173979 executions combine admission, client/entity clear, actual247520 initialization or247219 restore, bot admission and completion. The corpus includes ordinary auth denial, localhost, partial addresses with supplied scratch, bot bypass/failure, negative new-session control, both lifecycle choices and mode0/3/9. Full6336-byte client checksums accompany watched words, the944-byte session block, entity state, exact messages, ordered events/cvar writes/reads and selector/formatter carry. The checksum is an FNV-1a coverage check, not a cryptographic identity claim.
|
| 35 |
+
|
| 36 |
+
Authentication denial leaves client/entity state intact. Bot rejection occurs later and retains prior lifecycle effects, including cvar/file intentions. Initialization can serialize timeout60100 before a first-time suffix overwrites the in-memory value with100; no second persistence write occurs in this caller. Stable engine userinfo snapshots are supplied across nested reads in this corpus. Mutating globals/counts between callbacks, raw VM pointer aliasing and native engine resource/network behavior remain outside the verified domain.
|
| 37 |
+
|
| 38 |
+
The new helper qvm_connect_policy_support.py has a distinct filename. Original packed string regions are seeded directly from the verified QVM image, including initializer literals needed by the whole-call composition. Independent Python state/event oracles and Rust parity caught logical string boundary issues before commit. No original game binary or asset payload was modified.
|
| 39 |
+
|
| 40 |
+
## Validation
|
| 41 |
+
|
| 42 |
+
Every task ran focused `cargo xtask test-group <name>` before its own commit, with deterministic double regeneration, relevant source/Rust parity, scoped gameplay tests and storage/documentation/whitespace checks. Groups are qvm-byte-compare, rust-byte-compare, qvm-address-filter, rust-address-filter, qvm-connect-admission, rust-connect-admission, qvm-connect-tail, rust-connect-tail, qvm-connect-complete and rust-connect-complete. Shared admission/address/tail helpers also received focused regression checks.
|
| 43 |
+
|
| 44 |
+
Dependency-selection regression coverage includes the five new source/Rust report pairs, native_policy consumers and intermission/formatting dependencies. The existing health/session helper import smoke check remains in place. Every Python process uses the resolved Nix runtime declared by flake.nix, with explicit PYTHON for xtask and Git hooks. After commit ten, `cargo xtask test-full --since 2b1ac7ec` passed on its first full attempt: 1,783 Python tests and216 Rust tests (assets10, gameplay176, xtask30). All32 affected report producers regenerated twice deterministically. Storage policy, links across491 documentation files and whitespace checks passed with no generated-report drift. Validation notes were amended into task ten.
|
| 45 |
+
|
| 46 |
+
## Next work: RE-924
|
| 47 |
+
|
| 48 |
+
- [ ] Recover161744 bot admission,171668 userinfo mutation and182896 team-join callback bodies, then compose them with173979 and actual5864 ranking/publication.
|
| 49 |
+
- [ ] Recover address-filter table writers and native IP/userinfo provenance; verify partial-address stack provenance, aliases, malformed counts and live configuration changes.
|
| 50 |
+
- [ ] Recover native logging/network/cvar/file-open and handle ownership, attach real engine adapters and validate actual connect/reload/failure behavior on macOS/Linux.
|
| 51 |
+
- [ ] Extend scalar/string domains: non-ASCII tails, uppercase exponents, remaining scanf conversions, oversized/fatal strings and native pointer boundaries.
|
| 52 |
+
- [ ] Compose both persistence children into series6939/readiness, native command dispatch, bot rotation/genetics and221662 map-list parsing.
|
| 53 |
+
- [ ] Replace supplied spatial-query answers with recovered native broadphase/world collision and compare native math.
|
| 54 |
+
- [ ] Compose complete respawn/intermission, event lifetime and scoreboard/network execution.
|
| 55 |
+
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
docs/research/QVM_SESSION_LIFECYCLE_BATCH.md
CHANGED
|
@@ -43,7 +43,7 @@ Focused `cargo xtask test-group <name>` ran before each commit, with selected re
|
|
| 43 |
|
| 44 |
The dependency-selection regression covers the five source/Rust report pairs, native_policy consumers and shared transition/map/intermission dependencies. Its import smoke check also keeps the existing health lifecycle and new session lifecycle helper namespaces independent. The first full-suite attempt caught a helper filename collision: the original health helper was restored byte-for-byte from the batch baseline, the new code moved to qvm_session_lifecycle_support.py, and affected checks were rerun before final full validation. Python runs only through the resolved Nix runtime declared by flake.nix, with explicit PYTHON inherited by xtask and Git hooks. Original assets are unchanged. After the namespace repair documented above, `cargo xtask test-full --since 6d0ce63f` completed successfully at the tenth-commit boundary: 1,768 Python tests and207 Rust tests (assets10, gameplay167, xtask30). All39 affected report producers regenerated twice deterministically. Storage policy, links across480 documentation files and whitespace checks passed with no generated-report drift. Repair and validation notes were amended into task ten.
|
| 45 |
|
| 46 |
-
##
|
| 47 |
|
| 48 |
- [ ] Recover the173979 authentication/userinfo prefix and post-174174 team normalization, bot branch and downstream connect callbacks; compose the complete function.
|
| 49 |
- [ ] Recover native file-open return/handle/close behavior and attach a platform-neutral engine IO adapter; validate actual reload and failure ownership on macOS/Linux.
|
|
@@ -53,3 +53,5 @@ The dependency-selection regression covers the five source/Rust report pairs, na
|
|
| 53 |
- [ ] Replace supplied spatial-query answers with native broadphase/world collision and compare native math.
|
| 54 |
- [ ] Compose complete respawn/intermission, event lifetime and ranking/scoreboard/network execution.
|
| 55 |
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
The dependency-selection regression covers the five source/Rust report pairs, native_policy consumers and shared transition/map/intermission dependencies. Its import smoke check also keeps the existing health lifecycle and new session lifecycle helper namespaces independent. The first full-suite attempt caught a helper filename collision: the original health helper was restored byte-for-byte from the batch baseline, the new code moved to qvm_session_lifecycle_support.py, and affected checks were rerun before final full validation. Python runs only through the resolved Nix runtime declared by flake.nix, with explicit PYTHON inherited by xtask and Git hooks. Original assets are unchanged. After the namespace repair documented above, `cargo xtask test-full --since 6d0ce63f` completed successfully at the tenth-commit boundary: 1,768 Python tests and207 Rust tests (assets10, gameplay167, xtask30). All39 affected report producers regenerated twice deterministically. Storage policy, links across480 documentation files and whitespace checks passed with no generated-report drift. Repair and validation notes were amended into task ten.
|
| 45 |
|
| 46 |
+
## Follow-up work (expanded by RE-914–923)
|
| 47 |
|
| 48 |
- [ ] Recover the173979 authentication/userinfo prefix and post-174174 team normalization, bot branch and downstream connect callbacks; compose the complete function.
|
| 49 |
- [ ] Recover native file-open return/handle/close behavior and attach a platform-neutral engine IO adapter; validate actual reload and failure ownership on macOS/Linux.
|
|
|
|
| 53 |
- [ ] Replace supplied spatial-query answers with native broadphase/world collision and compare native math.
|
| 54 |
- [ ] Compose complete respawn/intermission, event lifetime and ranking/scoreboard/network execution.
|
| 55 |
- [ ] Validate actual Linux/macOS Rust/Bevy/Solari gameplay/rendering. Full-game completion remains open.
|
| 56 |
+
|
| 57 |
+
[RE-914–923](QVM_CONNECT_POLICY_BATCH.md) recovers admission/completion and composes the complete bounded173979 caller. Its RE-924 list supersedes the historical follow-up list above.
|
docs/research/README.md
CHANGED
|
@@ -1378,3 +1378,9 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 1378 |
|
| 1379 |
|
| 1380 |
[RE-922: Complete original connect caller with recovered admission/lifecycle/tail](QVM_CONNECT_COMPLETE.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1378 |
|
| 1379 |
|
| 1380 |
[RE-922: Complete original connect caller with recovered admission/lifecycle/tail](QVM_CONNECT_COMPLETE.md).
|
| 1381 |
+
|
| 1382 |
+
|
| 1383 |
+
[RE-923: Rust complete connect policy composition](RUST_CONNECT_COMPLETE.md).
|
| 1384 |
+
|
| 1385 |
+
|
| 1386 |
+
[RE-914–923 complete connect caller policy batch](QVM_CONNECT_POLICY_BATCH.md).
|
docs/research/RUST_CONNECT_COMPLETE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Rust complete connect policy composition
|
| 2 |
+
|
| 3 |
+
RE-923. Reproduce with `python3 scripts/analyze_rust_connect_complete.py`; focused validation: `cargo xtask test-group rust-connect-complete`. [Machine report](rust-connect-complete.json).
|
| 4 |
+
|
| 5 |
+
Rust matches96 complete173979 executions across admission, client clear, initialization/restore, bot admission and callback completion. Auth denial preserves client/entity state; bot denial retains lifecycle effects. Source messages, cvar timing, full-client checksums, raw watched bytes and selector/formatter carry match. Native callback bodies, actual network/IO acceptance and runtime integration remain open.
|
| 6 |
+
|
| 7 |
+
Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
|
docs/research/rust-connect-complete.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
docs/research/rust-health-impulse.json
CHANGED
|
@@ -2985,7 +2985,7 @@
|
|
| 2985 |
"exit_code": 2
|
| 2986 |
}
|
| 2987 |
],
|
| 2988 |
-
"rust_unit_tests":
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
|
|
|
| 2985 |
"exit_code": 2
|
| 2986 |
}
|
| 2987 |
],
|
| 2988 |
+
"rust_unit_tests": 176,
|
| 2989 |
"source_report": "docs/research/qvm-health-impulse.json",
|
| 2990 |
"source_report_sha256": "625fd8064004ea6dbdf398d51d0af844d9c635ff04c0a0790886dddb6ab81e71"
|
| 2991 |
}
|
scripts/analyze_rust_connect_complete.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import hashlib,json
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
from rust_native_policy_support import binary,result,invoke
|
| 5 |
+
from analyze_qvm import write_json
|
| 6 |
+
def blob(s):return [len(bytes.fromhex(s)),*bytes.fromhex(s)]
|
| 7 |
+
def encode(s):
|
| 8 |
+
a=s['input'];return [a[k] for k in ['mode','first','new','bot','answer','scratch','filter_scratch','changed']]+[len(a['entries']),*[v for row in a['entries'] for v in row],*blob(a['userinfo']),*blob(a['password'])]
|
| 9 |
+
def project(s):return {k:s[k] for k in ['accepted','message','steps','filter','events','choice','raw','client_checksum','words','entity','sets','reads','ring','info_ring']}
|
| 10 |
+
|
| 11 |
+
def main():
|
| 12 |
+
b=binary();p=Path('docs/research/qvm-connect-complete.json');data=p.read_bytes();rows=[]
|
| 13 |
+
for s in json.loads(data)['probes']:rows.append({'source':project(s),'rust':result(b,'connect-complete',encode(s))})
|
| 14 |
+
write_json(Path('docs/research/rust-connect-complete.json'),{'source_report':str(p),'source_report_sha256':hashlib.sha256(data).hexdigest(),'probes':rows,'limits':'Rust matches96 complete173979 executions across admission, client clear, initialization/restore, bot admission and callback completion. Auth denial preserves client/entity state; bot denial retains lifecycle effects. Source messages, cvar timing, full-client checksums, raw watched bytes and selector/formatter carry match. Native callback bodies, actual network/IO acceptance and runtime integration remain open.'})
|
| 15 |
+
if __name__=='__main__':main()
|
scripts/test_rust_connect_complete.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import hashlib,json,unittest
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
class PortTests(unittest.TestCase):
|
| 4 |
+
def test_all_original_cases(self):
|
| 5 |
+
r=json.loads(Path('docs/research/rust-connect-complete.json').read_text());src=json.loads(Path(r['source_report']).read_text());self.assertEqual(len(r['probes']),len(src['probes']));self.assertGreater(len(r['probes']),20)
|
| 6 |
+
for p in r['probes']:self.assertEqual(p['rust'],p['source'])
|
| 7 |
+
def test_source_identity(self):
|
| 8 |
+
r=json.loads(Path('docs/research/rust-connect-complete.json').read_text());self.assertEqual(hashlib.sha256(Path(r['source_report']).read_bytes()).hexdigest(),r['source_report_sha256'])
|
| 9 |
+
if __name__=='__main__':unittest.main()
|
xtask/checks.tsv
CHANGED
|
@@ -2990,3 +2990,18 @@ edge scripts/analyze_qvm_connect_complete.py scripts/analyze_qvm_resumer_audit.p
|
|
| 2990 |
edge scripts/qvm_connect_complete_oracle.py scripts/analyze_qvm_resumer_audit.py
|
| 2991 |
group qvm-connect-complete scripts/analyze_qvm_connect_admission.py
|
| 2992 |
group qvm-connect-complete scripts/analyze_qvm_address_filter.py
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2990 |
edge scripts/qvm_connect_complete_oracle.py scripts/analyze_qvm_resumer_audit.py
|
| 2991 |
group qvm-connect-complete scripts/analyze_qvm_connect_admission.py
|
| 2992 |
group qvm-connect-complete scripts/analyze_qvm_address_filter.py
|
| 2993 |
+
edge Cargo.toml scripts/analyze_rust_connect_complete.py
|
| 2994 |
+
edge Cargo.lock scripts/analyze_rust_connect_complete.py
|
| 2995 |
+
edge crates/urt-gameplay/Cargo.toml scripts/analyze_rust_connect_complete.py
|
| 2996 |
+
edge crates/urt-gameplay/src/lib.rs scripts/analyze_rust_connect_complete.py
|
| 2997 |
+
edge crates/urt-gameplay/src/native_policy.rs scripts/analyze_rust_connect_complete.py
|
| 2998 |
+
edge crates/urt-gameplay/src/bin/urt-native-policy.rs scripts/analyze_rust_connect_complete.py
|
| 2999 |
+
edge docs/research/qvm-connect-complete.json scripts/analyze_rust_connect_complete.py
|
| 3000 |
+
group rust-connect-complete scripts/analyze_rust_health_impulse.py
|
| 3001 |
+
group gameplay scripts/analyze_rust_connect_complete.py
|
| 3002 |
+
edge crates/urt-gameplay/src/intermission.rs scripts/analyze_rust_connect_complete.py
|
| 3003 |
+
edge crates/urt-gameplay/src/qvm_format.rs scripts/analyze_rust_connect_complete.py
|
| 3004 |
+
report scripts/analyze_rust_connect_complete.py docs/research/rust-connect-complete.json
|
| 3005 |
+
edge docs/research/rust-connect-complete.json scripts/test_rust_connect_complete.py
|
| 3006 |
+
group rust-connect-complete scripts/analyze_rust_connect_complete.py
|
| 3007 |
+
edge scripts/analyze_rust_connect_complete.py scripts/analyze_qvm_resumer_audit.py
|
xtask/src/lib.rs
CHANGED
|
@@ -1117,6 +1117,12 @@ mod integration_tests {
|
|
| 1117 |
("map_commands", "normal_map_files"),
|
| 1118 |
("transition", "normal_map_files"),
|
| 1119 |
("intermission", "connect_session"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1120 |
("protected", "protected_update"),
|
| 1121 |
("mode10", "mode10_entry"),
|
| 1122 |
("intercept_animation", "mode10_animation"),
|
|
@@ -1196,6 +1202,11 @@ mod integration_tests {
|
|
| 1196 |
("qvm-normal-map-files", "normal_map_files"),
|
| 1197 |
("qvm-persistence-roundtrip", "persistence_roundtrip"),
|
| 1198 |
("qvm-connect-session", "connect_session"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1199 |
("qvm-rank-small-sort", "rank_sort"),
|
| 1200 |
("qvm-rank-large-sort", "rank_sort"),
|
| 1201 |
("qvm-ranking-complete", "ranking_complete"),
|
|
|
|
| 1117 |
("map_commands", "normal_map_files"),
|
| 1118 |
("transition", "normal_map_files"),
|
| 1119 |
("intermission", "connect_session"),
|
| 1120 |
+
("native_policy", "byte_compare"),
|
| 1121 |
+
("native_policy", "address_filter"),
|
| 1122 |
+
("native_policy", "connect_admission"),
|
| 1123 |
+
("native_policy", "connect_tail"),
|
| 1124 |
+
("native_policy", "connect_complete"),
|
| 1125 |
+
("intermission", "connect_complete"),
|
| 1126 |
("protected", "protected_update"),
|
| 1127 |
("mode10", "mode10_entry"),
|
| 1128 |
("intercept_animation", "mode10_animation"),
|
|
|
|
| 1202 |
("qvm-normal-map-files", "normal_map_files"),
|
| 1203 |
("qvm-persistence-roundtrip", "persistence_roundtrip"),
|
| 1204 |
("qvm-connect-session", "connect_session"),
|
| 1205 |
+
("qvm-byte-compare", "byte_compare"),
|
| 1206 |
+
("qvm-address-filter", "address_filter"),
|
| 1207 |
+
("qvm-connect-admission", "connect_admission"),
|
| 1208 |
+
("qvm-connect-tail", "connect_tail"),
|
| 1209 |
+
("qvm-connect-complete", "connect_complete"),
|
| 1210 |
("qvm-rank-small-sort", "rank_sort"),
|
| 1211 |
("qvm-rank-large-sort", "rank_sort"),
|
| 1212 |
("qvm-ranking-complete", "ranking_complete"),
|