Complete authenticated interactive prompt routing

This commit is contained in:
ms2k 2026-07-17 07:20:21 +09:00
commit 46b52b4b43

View file

@ -3,7 +3,8 @@ use std::fs::File;
use std::io;
use lazaret_client::terminal::{
HostTerminal, HostTerminalEvent, InteractiveSessionTransport, run_interactive_session,
HostTerminal, HostTerminalEvent, InteractiveSessionTransport, PromptOutcome,
run_interactive_session,
};
use lazaret_client::{ClientError, ClientSessionIdentity};
use lazaret_core::identity::{
@ -106,11 +107,21 @@ impl HostTerminal for PtyTerminal {
Ok(())
}
fn prompt(&mut self, prompt: &TerminalPrompt) -> io::Result<DeveloperDecisionKind> {
fn prompt(&mut self, prompt: &TerminalPrompt) -> io::Result<PromptOutcome> {
assert_eq!(prompt.agent_profile, "trusted");
assert_eq!(prompt.command_argv, [b"/usr/bin/tool".to_vec()]);
assert_eq!(prompt.justification, "update host metadata");
Ok(self.decision)
let resumed_size = if matches!(self.events.front(), Some(HostTerminalEvent::LocalSuspend)) {
self.events.pop_front();
self.suspend_and_resume()?;
Some(self.size(prompt.session_id)?)
} else {
None
};
Ok(PromptOutcome {
decision: self.decision,
resumed_size,
})
}
fn suspend_and_resume(&mut self) -> io::Result<()> {
@ -132,6 +143,7 @@ struct FixtureTransport {
prompt_sent: bool,
failure: Option<TransportFailure>,
signed_decision: Option<Vec<u8>>,
prompt_after_events: usize,
}
impl FixtureTransport {
@ -142,6 +154,7 @@ impl FixtureTransport {
prompt_sent: false,
failure: None,
signed_decision: None,
prompt_after_events: 5,
}
}
}
@ -188,7 +201,7 @@ impl InteractiveSessionTransport for FixtureTransport {
)],
));
}
if !self.prompt_sent && self.events.len() >= 5 {
if !self.prompt_sent && self.events.len() >= self.prompt_after_events {
self.prompt_sent = true;
return Ok(batch(
self.session_id,
@ -206,6 +219,39 @@ impl InteractiveSessionTransport for FixtureTransport {
}
}
#[test]
fn prompt_suspend_sends_resumed_size_before_decision() {
let identity = ClientSessionIdentity::generate::<std::convert::Infallible>().unwrap();
let binding = binding(&identity);
let mut terminal = PtyTerminal::new([HostTerminalEvent::Idle, HostTerminalEvent::LocalSuspend]);
let mut transport = FixtureTransport::successful(identity.session_id());
transport.prompt_after_events = 1;
assert_eq!(
run_interactive_session(
&mut transport,
&mut terminal,
&identity,
&binding,
&[b"/bin/sh".to_vec()],
)
.unwrap(),
23
);
assert_eq!(terminal.suspend_count, 1);
assert!(matches!(
transport.events.as_slice(),
[
InteractiveSessionEvent::Poll { .. },
InteractiveSessionEvent::Terminal(lazaret_core::records::SessionTerminalEvent::Resize(
_
)),
InteractiveSessionEvent::PromptDecision { .. }
]
));
}
#[test]
fn terminal_fixture_routes_resize_signals_suspend_prompt_and_nonzero_exit() {
let identity = ClientSessionIdentity::generate::<std::convert::Infallible>().unwrap();