Done the way the owner asked and the spike mapped: the crate and the manifests renamed, then what the build reported fixed. Layers: 138 "proto unresolved" errors across 169 files; cargo fmt reordering imports; six fixture paths built as strings in brokerd's and bxctl's tests, which the compiler cannot see, and comments naming crates/proto/; the crate-dependency check and its self-test. One more the spike did not reach: a `\nproto =` key inside a printf format in the self-test, which a word-boundary replacement skips because `n` and `p` are both word characters. make gate: gate: ok, 944 tests; no new entry in /tmp. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
98 lines
2.8 KiB
Rust
98 lines
2.8 KiB
Rust
//! `brokerd`'s side of one `gateway.sock` connection, for tests: ask, read what comes back,
|
|
//! answer with an outcome, or close. Do not edit.
|
|
|
|
#![allow(dead_code)] // each test file uses a different part of this module
|
|
|
|
use std::os::unix::net::UnixStream;
|
|
use std::path::Path;
|
|
use std::time::Duration;
|
|
|
|
use bxcore::{
|
|
ApprovalOutcome, ApprovalReply, ApprovalRequest, CallId, DataClass, Envelope, GatewayOutcome,
|
|
Message, PROTOCOL_VERSION, PendingApproval, SessionId, Timestamp, read_frame, write_frame,
|
|
};
|
|
|
|
pub struct Asking {
|
|
stream: UnixStream,
|
|
pub posts: Vec<String>,
|
|
}
|
|
|
|
/// An approval of `session`, with these arguments.
|
|
pub fn pending(approval: u64, session: &str, arguments: &str) -> PendingApproval {
|
|
PendingApproval {
|
|
approval,
|
|
session: SessionId::new(session).unwrap(),
|
|
call: CallId(3),
|
|
tool: "read_file".to_string(),
|
|
arguments: arguments.to_string(),
|
|
grant: "notes".to_string(),
|
|
taint: DataClass::Private,
|
|
created: Timestamp::parse("2026-09-24T08:05:00.000Z").unwrap(),
|
|
expires: Timestamp::parse("2026-09-24T08:20:00.000Z").unwrap(),
|
|
}
|
|
}
|
|
|
|
fn frame(id: u64, last: bool, msg: Message) -> Envelope {
|
|
Envelope {
|
|
v: PROTOCOL_VERSION,
|
|
id,
|
|
r#final: last,
|
|
msg,
|
|
}
|
|
}
|
|
|
|
/// Connect and ask; `Ok` with the posts, or `Err` with gatewayd's error detail.
|
|
pub fn ask(socket: &Path, info: PendingApproval) -> Result<Asking, String> {
|
|
let mut stream = UnixStream::connect(socket).map_err(|e| e.to_string())?;
|
|
stream
|
|
.set_read_timeout(Some(Duration::from_secs(10)))
|
|
.unwrap();
|
|
write_frame(
|
|
&mut stream,
|
|
&frame(
|
|
1,
|
|
true,
|
|
Message::ApprovalRequest(ApprovalRequest { approval: info }),
|
|
),
|
|
)
|
|
.unwrap();
|
|
match read_frame(&mut stream).map_err(|e| e.to_string())?.msg {
|
|
Message::ApprovalPosted(p) => Ok(Asking {
|
|
stream,
|
|
posts: p.posts,
|
|
}),
|
|
Message::Error(e) => Err(e.detail),
|
|
other => panic!("{other:?}"),
|
|
}
|
|
}
|
|
|
|
impl Asking {
|
|
/// The answer, within `wait`, or `None`.
|
|
pub fn answer(&mut self, wait: Duration) -> Option<ApprovalReply> {
|
|
self.stream.set_read_timeout(Some(wait)).unwrap();
|
|
match read_frame(&mut self.stream) {
|
|
Ok(Envelope {
|
|
msg: Message::ApprovalReply(r),
|
|
..
|
|
}) => Some(r),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn outcome(&mut self, outcome: GatewayOutcome) {
|
|
write_frame(
|
|
&mut self.stream,
|
|
&frame(
|
|
2,
|
|
true,
|
|
Message::ApprovalOutcome(ApprovalOutcome { outcome }),
|
|
),
|
|
)
|
|
.unwrap();
|
|
}
|
|
|
|
pub fn close(self) {
|
|
let _ = self.stream.shutdown(std::net::Shutdown::Both);
|
|
}
|
|
}
|