Downstream pressure
Texo is composing a resumable remote read-replica circuit over syncbat + netbat. The server path is complete and bounded (serve_tcp_listener, serve_stream, encode_response), and the client can use encode_request, but the public client-side response surface is asymmetric:
let request = netbat::encode_request("texo.replica.page.read", input);
stream.write_all(&request)?;
// No public decode_response / call_tcp equivalent exists.
decode_line only accepts NETBAT/1 CALL ... request frames. ResponseFrame is constructible, but OK <hex-output>\n / ERR <code> <hex-message>\n cannot be decoded through a public bounded API.
A downstream therefore has to duplicate protocol parsing, hex bounds, stable error-code handling, line termination, read deadlines, and EOF/truncation classification. That makes a supposedly shared boundary protocol less reusable and risks subtly different security limits per consumer.
Minimal reproducer
Against v0.10.0 / current main:
let wire = netbat::encode_response(Ok(b"hello"));
assert_eq!(wire, b"OK 68656c6c6f\n");
// Desired public inverse; no equivalent exists today.
let response = netbat::decode_response(&wire, &netbat::Limits::default())?;
assert_eq!(response.output(), b"hello");
The same gap exists for a one-request blocking client helper: downstream code must separately implement connect/read/write timeouts and bounded newline reads even though the server has canonical handling for those concerns.
Proposed neutral surface
Names are maintainer discretion; the contract matters:
pub enum DecodedResponse {
Ok(ResponseFrame),
Err { code: String, message: Vec<u8> },
}
pub fn decode_response(line: &[u8], limits: &Limits)
-> Result<DecodedResponse, NetbatError>;
pub fn call_tcp(
addr: SocketAddr,
operation: &str,
input: &[u8],
limits: &Limits,
timeouts: IoTimeouts,
) -> Result<ResponseFrame, NetbatError>;
call_tcp may be deferred if the decoder lands first. No async runtime is requested.
Acceptance criteria
decode_response(encode_response(Ok(bytes))) round-trips arbitrary bounded bytes.
- ERR code grammar is stable and validated; message bytes are hex-decoded under an explicit cap.
- Missing newline, extra fields, odd/non-hex payloads, unknown status tokens, EOF, and oversized lines fail with typed stable errors.
max_output_bytes is enforced on decoded OK bytes, not just hex text size.
- ERR messages use
max_stream_error_message_bytes or a dedicated request-response error cap.
- A blocking client helper, if included, enforces absolute/bounded connect, read, and write deadlines and never performs an unbounded
read_line.
- Property tests cover encode/decode round trips and total parsing over arbitrary input.
- Mutation tests kill removed size checks, token checks, and newline/truncation handling.
Downstream workaround
Texo will isolate a small parser/client in compat::netbat, tested against netbat::encode_response golden frames. It will be deleted in favor of the upstream API when shipped; no Texo vocabulary is needed upstream.
Downstream pressure
Texo is composing a resumable remote read-replica circuit over
syncbat+netbat. The server path is complete and bounded (serve_tcp_listener,serve_stream,encode_response), and the client can useencode_request, but the public client-side response surface is asymmetric:decode_lineonly acceptsNETBAT/1 CALL ...request frames.ResponseFrameis constructible, butOK <hex-output>\n/ERR <code> <hex-message>\ncannot be decoded through a public bounded API.A downstream therefore has to duplicate protocol parsing, hex bounds, stable error-code handling, line termination, read deadlines, and EOF/truncation classification. That makes a supposedly shared boundary protocol less reusable and risks subtly different security limits per consumer.
Minimal reproducer
Against
v0.10.0/ current main:The same gap exists for a one-request blocking client helper: downstream code must separately implement connect/read/write timeouts and bounded newline reads even though the server has canonical handling for those concerns.
Proposed neutral surface
Names are maintainer discretion; the contract matters:
call_tcpmay be deferred if the decoder lands first. No async runtime is requested.Acceptance criteria
decode_response(encode_response(Ok(bytes)))round-trips arbitrary bounded bytes.max_output_bytesis enforced on decoded OK bytes, not just hex text size.max_stream_error_message_bytesor a dedicated request-response error cap.read_line.Downstream workaround
Texo will isolate a small parser/client in
compat::netbat, tested againstnetbat::encode_responsegolden frames. It will be deleted in favor of the upstream API when shipped; no Texo vocabulary is needed upstream.