Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
319372c
test(network): require session.status command send
seonghobae Aug 30, 2026
03511d9
test(network): format session.status RED regression
seonghobae Aug 30, 2026
748a5c5
feat(network): send typed BiDi session.status command
seonghobae Aug 30, 2026
4b6eeea
style(network): apply canonical session.status rustfmt
seonghobae Aug 30, 2026
2607a22
test(network): cover session.status fail-closed send paths
seonghobae Aug 30, 2026
491176c
test(network): remove vacuous session.status coverage branch
seonghobae Aug 30, 2026
9c8dd8b
test(network): keep production coverage scoped to production code
seonghobae Aug 30, 2026
bdc338b
style(network): apply canonical session.status test formatting
seonghobae Aug 30, 2026
c4c969f
fix(network): remove unstable coverage attribute
seonghobae Aug 30, 2026
45956f2
test(network): avoid residual branch in session.status serialization
seonghobae Aug 30, 2026
4e0d5e8
test(network): name session.status handshake fixture type
seonghobae Aug 30, 2026
d0876f1
test(network): cover both session.status id-range paths
seonghobae Aug 30, 2026
0230ae5
test(network): exercise rejected session.status ids externally
seonghobae Aug 30, 2026
f6ad019
style(network): apply canonical rustfmt
seonghobae Aug 30, 2026
04d6c12
test(network): bind session.status response kind
seonghobae Sep 1, 2026
8b5b454
test(network): bind duplicate status command kind
seonghobae Sep 1, 2026
9e4a64f
fix(network): bind session.status correlation kind
seonghobae Sep 1, 2026
f9ec8f4
fix(network): expose command kind to status slice
seonghobae Sep 1, 2026
f347273
merge(network): converge session.status on command-kind correlation
seonghobae Sep 1, 2026
9863d4f
restack(network): adopt repaired command-correlation parent
seonghobae Sep 3, 2026
9ab8181
chore(network): adopt verified BiDi correlation root
seonghobae Sep 4, 2026
eca63e0
style(network): preserve canonical trailing newline after restack
seonghobae Sep 4, 2026
06cf25f
test(network): reject invalid BiDi frame deadline before correlation
seonghobae Sep 4, 2026
0f71dac
fix(network): reject invalid BiDi frame deadline before correlation
seonghobae Sep 4, 2026
2b73482
test(network): cover both invalid BiDi frame deadline bounds
seonghobae Sep 4, 2026
3c9124b
docs(network): distinguish BiDi frame preflight from write ambiguity
seonghobae Sep 4, 2026
b293b35
test(network): expose pre-I/O mask reuse correlation leak
seonghobae Sep 4, 2026
8c7b975
fix(network): retire correlation on pre-I/O mask rejection
seonghobae Sep 4, 2026
b9e38b4
test(network): name mask-reuse outcome precisely
seonghobae Sep 4, 2026
0c6a6da
docs(network): doctor session.status transport contract
seonghobae Sep 4, 2026
117d759
docs(network): record bounded session.status command
seonghobae Sep 4, 2026
588514b
docs(network): correct current BiDi editor draft date
seonghobae Sep 4, 2026
422ac8c
docs: preserve RFC 5280 reference author
seonghobae Sep 4, 2026
6860fc5
merge(parent): refresh session status command base
seonghobae Sep 4, 2026
2636564
test(network): close session status coverage gap
seonghobae Sep 5, 2026
4438718
merge(parent): refresh session status base
seonghobae Sep 5, 2026
2279d18
merge(parent): refresh session status base
seonghobae Sep 5, 2026
017d6e8
merge: restack session status on current correlation
seonghobae Sep 5, 2026
84b9407
fix(network): adopt verified command correlation parent
seonghobae Sep 5, 2026
e77150f
fix: bind session.status to sender connection
seonghobae Sep 6, 2026
583ffee
repair(network): restore BiDi connection provenance prerequisite
seonghobae Sep 6, 2026
65ac3ab
fix(network): keep response provenance in child slice
seonghobae Sep 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to OriginWeave are documented in this file. The format follo
### Added

- Bounded RFC 6455 WebDriver BiDi opening-response validation on the exact peer-verified stream: it admits only HTTP/1.1 `101`, case-insensitive `Upgrade`/`Connection` tokens, and the client-key-correlated `Sec-WebSocket-Accept` value within monotonic time and header-size ceilings; it restores blocking mode and still does not implement WebSocket frames or grant browser/Agent authority.
- Typed outbound WebDriver BiDi `session.status` over the bounded client WebSocket stream: it serializes only the standards-defined method with empty params, preserves exact typed command-id correlation, rejects invalid frame deadlines before registration, retires only the just-registered id when a local masking-key preflight proves no command bytes were emitted, and keeps correlation outstanding after partial or ambiguous writes; frame-write success is not treated as command completion or browser/Agent authority.
- Bounded WebDriver BiDi loopback TCP transport that consumes one exact no-DNS connect target, retries only explicitly recoverable local transport failures within repository timeout and attempt ceilings, exposes the stream only after operating-system peer inspection and exact peer verification, supports a consuming handoff of the original stream with typed credential-free peer/session/TLS and bounded-attempt evidence, preserves typed causal errors, and performs no DNS, proxy/PAC, process authentication, TLS, WebSocket, BiDi message, browser-action, or Agent-authority step.
- Exact WebDriver BiDi socket-peer verification that consumes an approved no-DNS connect target, requires the observed IP address and port to match exactly, preserves the TLS requirement and exact correlated session id, and remains inert metadata that does not authenticate an OS process, does not negotiate TLS, perform a WebSocket handshake, or grant Agent authority.
- Explicit no-DNS WebDriver BiDi loopback connection targets that derive exact IPv4/IPv6 loopback `SocketAddr` metadata from a session-correlated endpoint, reject `localhost` as requiring separately trusted name resolution, preserve the TLS requirement and exact session id, perform no socket I/O, and grant no Agent authority.
Expand Down Expand Up @@ -55,7 +56,9 @@ All notable changes to OriginWeave are documented in this file. The format follo

### Changed

- Kept the `session.status` frame-failure coverage contract focused on observable correlation state, avoiding assertion-internal uncovered branches without weakening preflight retirement or ambiguous-write retention checks.
- Made the command-correlation release-record check run in the existing CI test suite, preserving its exact bounds and authority exclusions; carried the verified message-parent fixture repairs into the correlation stack.
- Carried the verified parent fixture and release-check repairs into the session-status sender without changing command or correlation behavior.
- Aligned the bounded WebDriver BiDi error-envelope vocabulary with the current specification by admitting the defined `no such client window` response while retaining fail-closed rejection of unknown error codes.
- Separated logical origin authority from resolved network destination authority; an origin grant no longer implies permission to connect to every resolver result.
- Separated resolved-address authorization from direct transport evidence; an approved IP now becomes a usable stream only after the operating system reports the exact requested IP and port.
Expand Down
11 changes: 8 additions & 3 deletions crates/originweave-network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
//! `originweave-core` into one bounded exact TCP connection, binds and validates
//! the RFC 6455 opening exchange, provides bounded masked client writes and
//! unmasked server-frame reads, assembles bounded WebDriver BiDi text messages,
//! classifies complete local-end JSON envelopes, and tracks bounded command-response
//! correlation without exposing generic JSON bodies or granting browser, TLS,
//! policy, secret, or Agent authority.
//! classifies complete local-end JSON envelopes, tracks bounded command-response
//! correlation, and sends one narrowly typed `session.status` command without
//! exposing generic JSON bodies or granting browser, TLS, policy, secret, or
//! Agent authority.

#![forbid(unsafe_code)]
#![deny(missing_docs)]
Expand All @@ -18,6 +19,7 @@ mod connection;
mod webdriver_bidi_command_correlation;
mod webdriver_bidi_connection;
mod webdriver_bidi_json_envelope;
mod webdriver_bidi_session_status_command;
mod webdriver_bidi_websocket_frame;
mod webdriver_bidi_websocket_handshake;
mod webdriver_bidi_websocket_message;
Expand All @@ -44,6 +46,9 @@ pub use webdriver_bidi_json_envelope::{
MAX_WEBDRIVER_BIDI_JS_UINT, MAX_WEBDRIVER_BIDI_JSON_DEPTH, WebDriverBiDiJsonEnvelope,
WebDriverBiDiJsonEnvelopeError, WebDriverBiDiJsonEnvelopeKind,
};
pub use webdriver_bidi_session_status_command::{
WebDriverBiDiSessionStatusCommand, WebDriverBiDiSessionStatusCommandError,
};
pub use webdriver_bidi_websocket_frame::{
MAX_WEBSOCKET_FRAME_PAYLOAD_SIZE, MAX_WEBSOCKET_FRAME_TIMEOUT,
WebDriverBiDiWebSocketEstablished, WebDriverBiDiWebSocketFrame,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{collections::BTreeMap, error::Error, fmt};

use crate::{
MAX_WEBDRIVER_BIDI_JS_UINT, WebDriverBiDiJsonEnvelope, WebDriverBiDiJsonEnvelopeRouting,
webdriver_bidi_connection::WebDriverBiDiConnectionGeneration,
};

/// Maximum number of local WebDriver BiDi commands retained as outstanding at once.
Expand All @@ -25,6 +26,12 @@ pub enum WebDriverBiDiCommandKind {
SessionEnd,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct OutstandingCommand {
kind: WebDriverBiDiCommandKind,
connection_generation: Option<WebDriverBiDiConnectionGeneration>,
}

/// Outcome of a response after it has consumed the matching outstanding command identifier.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WebDriverBiDiCorrelatedResponseOutcome {
Expand All @@ -36,12 +43,16 @@ pub enum WebDriverBiDiCorrelatedResponseOutcome {

/// Credential-free evidence that one parsed response consumed one outstanding local command.
///
/// This value carries only the matched command identifier and success/error classification. It
/// does not retain result bodies, error text, browser authority, transport authority, or secrets.
/// This value carries only the matched command identifier and success/error classification. A
/// private process-local connection generation is retained when the command owner bound one before
/// I/O so a later response-provenance owner can compare transport evidence without accepting
/// caller-supplied provenance. It does not retain result bodies, error text, browser authority,
/// transport authority, or secrets.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WebDriverBiDiCorrelatedResponse {
command_id: u64,
outcome: WebDriverBiDiCorrelatedResponseOutcome,
connection_generation: Option<WebDriverBiDiConnectionGeneration>,
}

impl WebDriverBiDiCorrelatedResponse {
Expand Down Expand Up @@ -76,6 +87,16 @@ pub enum WebDriverBiDiCommandCorrelationError {
/// Command family actually registered for the outstanding identifier.
actual: WebDriverBiDiCommandKind,
},
/// A connection-bound consumer found an outstanding command with no connection provenance.
CommandConnectionProvenanceMissing {
/// Exact outstanding local command identifier.
command_id: u64,
},
/// The response was received on a different verified connection from the outstanding command.
ResponseConnectionMismatch {
/// Exact outstanding local command identifier left untouched after rejection.
command_id: u64,
},
/// An event is not a command response and cannot consume correlation state.
EventIsNotResponse,
/// A protocol error with a `null` id cannot be attributed to one outstanding command.
Expand All @@ -92,6 +113,12 @@ impl fmt::Display for WebDriverBiDiCommandCorrelationError {
Self::CommandKindMismatch { .. } => {
"WebDriver BiDi response command kind does not match the outstanding command"
}
Self::CommandConnectionProvenanceMissing { .. } => {
"WebDriver BiDi outstanding command lacks connection provenance"
}
Self::ResponseConnectionMismatch { .. } => {
"WebDriver BiDi response arrived on a different connection"
}
Self::EventIsNotResponse => "WebDriver BiDi event cannot be correlated as a response",
Self::UncorrelatableErrorResponse => {
"WebDriver BiDi error response has no correlatable command id"
Expand All @@ -106,14 +133,16 @@ impl Error for WebDriverBiDiCommandCorrelationError {}
/// Bounded local WebDriver BiDi command-response correlation state.
///
/// Register an id together with its exact typed command family only after the caller has committed
/// to that outbound command. A success or correlatable error response consumes the id exactly once
/// only through a matching typed consumer. Events, null-id errors, and command-kind mismatches leave
/// outstanding state untouched. This type performs no I/O, retry, command serialization, browser
/// authentication, or authority grant. Debug output reports only the outstanding-count summary;
/// command identifiers and command families remain private correlation state.
/// to that outbound command. Connection-owning command adapters may additionally bind the private
/// generation of the exact established transport before I/O. Generic success or correlatable error
/// responses consume the id exactly once through a matching typed consumer; a later slice that owns
/// received-connection evidence adds the connection-sensitive consuming boundary. This type
/// performs no I/O, retry, command serialization, browser authentication, or authority grant. Debug
/// output reports only the outstanding-count summary; command identifiers, families, and
/// generations remain private correlation state.
#[derive(Default)]
pub struct WebDriverBiDiCommandCorrelation {
outstanding: BTreeMap<u64, WebDriverBiDiCommandKind>,
outstanding: BTreeMap<u64, OutstandingCommand>,
}

impl fmt::Debug for WebDriverBiDiCommandCorrelation {
Expand Down Expand Up @@ -147,6 +176,24 @@ impl WebDriverBiDiCommandCorrelation {
&mut self,
command_id: u64,
command_kind: WebDriverBiDiCommandKind,
) -> Result<(), WebDriverBiDiCommandCorrelationError> {
self.register(command_id, command_kind, None)
}

pub(crate) fn register_command_for_connection(
&mut self,
command_id: u64,
command_kind: WebDriverBiDiCommandKind,
connection_generation: WebDriverBiDiConnectionGeneration,
) -> Result<(), WebDriverBiDiCommandCorrelationError> {
self.register(command_id, command_kind, Some(connection_generation))
}

fn register(
&mut self,
command_id: u64,
command_kind: WebDriverBiDiCommandKind,
connection_generation: Option<WebDriverBiDiConnectionGeneration>,
) -> Result<(), WebDriverBiDiCommandCorrelationError> {
if command_id > MAX_WEBDRIVER_BIDI_JS_UINT {
return Err(WebDriverBiDiCommandCorrelationError::CommandIdOutOfRange);
Expand All @@ -157,7 +204,13 @@ impl WebDriverBiDiCommandCorrelation {
if self.outstanding.len() >= MAX_WEBDRIVER_BIDI_OUTSTANDING_COMMANDS {
return Err(WebDriverBiDiCommandCorrelationError::OutstandingCommandLimit);
}
let _previous = self.outstanding.insert(command_id, command_kind);
let _previous = self.outstanding.insert(
command_id,
OutstandingCommand {
kind: command_kind,
connection_generation,
},
);
Ok(())
}

Expand All @@ -179,7 +232,8 @@ impl WebDriverBiDiCommandCorrelation {
///
/// Successful responses and error responses with ids consume exactly one matching command.
/// Unknown ids and command-kind mismatches fail without consuming state. Events and null-id
/// errors fail before touching the map.
/// errors fail before touching the map. This generic path does not claim received-connection
/// provenance; connection-sensitive response handling belongs to its owning child slice.
pub fn correlate_response_for(
&mut self,
envelope: &WebDriverBiDiJsonEnvelope,
Expand Down Expand Up @@ -211,19 +265,19 @@ impl WebDriverBiDiCommandCorrelation {
&self,
command_id: u64,
expected_kind: WebDriverBiDiCommandKind,
) -> Result<(), WebDriverBiDiCommandCorrelationError> {
) -> Result<OutstandingCommand, WebDriverBiDiCommandCorrelationError> {
let actual = self
.outstanding
.get(&command_id)
.copied()
.ok_or(WebDriverBiDiCommandCorrelationError::CommandNotOutstanding)?;
if actual != expected_kind {
if actual.kind != expected_kind {
return Err(WebDriverBiDiCommandCorrelationError::CommandKindMismatch {
expected: expected_kind,
actual,
actual: actual.kind,
});
}
Ok(())
Ok(actual)
}

fn complete(
Expand All @@ -232,11 +286,12 @@ impl WebDriverBiDiCommandCorrelation {
expected_kind: WebDriverBiDiCommandKind,
outcome: WebDriverBiDiCorrelatedResponseOutcome,
) -> Result<WebDriverBiDiCorrelatedResponse, WebDriverBiDiCommandCorrelationError> {
self.require_command_kind(command_id, expected_kind)?;
let outstanding = self.require_command_kind(command_id, expected_kind)?;
let _removed = self.outstanding.remove(&command_id);
Ok(WebDriverBiDiCorrelatedResponse {
command_id,
outcome,
connection_generation: outstanding.connection_generation,
})
}
}
Expand Down Expand Up @@ -271,6 +326,16 @@ mod tests {
},
"WebDriver BiDi response command kind does not match the outstanding command",
),
(
WebDriverBiDiCommandCorrelationError::CommandConnectionProvenanceMissing {
command_id: 7,
},
"WebDriver BiDi outstanding command lacks connection provenance",
),
(
WebDriverBiDiCommandCorrelationError::ResponseConnectionMismatch { command_id: 7 },
"WebDriver BiDi response arrived on a different connection",
),
(
WebDriverBiDiCommandCorrelationError::EventIsNotResponse,
"WebDriver BiDi event cannot be correlated as a response",
Expand Down
Loading
Loading