Implement PTY-native session terminal control

This commit is contained in:
ms2k 2026-08-02 17:36:40 +09:00
commit 8cef037fa3

View file

@ -13,8 +13,10 @@ use lazaret_core::identity::{
};
use lazaret_core::records::{
ClientEnrollmentResponse, ControlRequest, ControlResponse, Domain, DurableDecision, Generation,
GenerationIdentity, ProtocolVersion, Session, SessionBinding, SessionPhase,
SessionRegistrationRequest, SessionRegistrationResponse, TlsCredential,
GenerationIdentity, InteractiveSessionBatch, InteractiveSessionMessage,
InteractiveSessionRequest, ProtocolVersion, Session, SessionBinding, SessionPhase,
SessionRegistrationRequest, SessionRegistrationResponse, SessionTerminalMessage,
TerminalResize, TlsCredential,
};
use lazaret_host_coordinator::control::{
CONTROL_ALPN, ControlError, PendingClientEnrollment, PublishedControlFace, SessionRegistry,
@ -477,6 +479,47 @@ fn real_uds_tls_enrollment_and_registration_preserve_exact_profiles_and_session_
);
}
#[test]
fn v1_interactive_client_receives_an_explicit_upgrade_refusal() {
let directory = TestDirectory::new("interactive-v1-refusal");
let identity = generation_identity(7);
let (face, _) = publish(&directory, &identity);
let client = enroll(&face, ClientId::new(bytes(33)));
let binding = registration_binding(&identity, ClientId::new(bytes(33)), 34, 35);
let session_id = binding.session_id;
let (mut stream, serving, _) = open_registration(&face, &client, binding);
let initial_size = TerminalResize {
session_id,
rows: 24.try_into().unwrap(),
columns: 80.try_into().unwrap(),
pixel_width: 0,
pixel_height: 0,
};
PublishedControlFace::send(
&mut stream,
&ControlRequest::ExecuteInteractive(InteractiveSessionRequest {
protocol_version: ProtocolVersion::V1,
session_id,
argv: vec![b"sh".to_vec()],
initial_size,
}),
)
.unwrap();
let refusal: InteractiveSessionBatch = PublishedControlFace::receive(&mut stream).unwrap();
assert_eq!(refusal.session_id, session_id);
assert!(matches!(
refusal.messages.as_slice(),
[
InteractiveSessionMessage::Terminal(SessionTerminalMessage::Output(output)),
InteractiveSessionMessage::Terminal(SessionTerminalMessage::Exit(exit))
] if output.bytes == b"Lazaret interactive protocol upgrade required\r\n"
&& exit.outcome() == lazaret_core::records::SessionExitOutcome::RuntimeLost
));
drop(stream);
serving.join().unwrap().unwrap();
}
#[test]
fn duplicate_session_cli_and_anchor_identities_are_refused_while_registered() {
let directory = TestDirectory::new("duplicates");