Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
01c82b4
test(network): require typed BiDi text-input response admission
seonghobae Sep 1, 2026
c16e96c
feat(network): admit typed BiDi text-input results
seonghobae Sep 1, 2026
d72aff1
style(network): apply canonical rustfmt to text response
seonghobae Sep 1, 2026
8d4027e
style(network): apply canonical rustfmt to text response tests
seonghobae Sep 1, 2026
a9446fb
test(network): require text response family isolation
seonghobae Sep 6, 2026
5e465a8
merge: adopt current text transport security contracts
seonghobae Sep 6, 2026
cd93d9f
fix(network): correlate text responses with their command family
seonghobae Sep 6, 2026
ba43d61
docs: bound text response integration evidence
seonghobae Sep 6, 2026
4632f2d
test(network): reject text replies from replacement sockets
seonghobae Sep 6, 2026
d6889c8
fix(network): require sealed receipt provenance for text replies
seonghobae Sep 6, 2026
e1188c8
merge: integrate canonical text sender provenance
seonghobae Sep 6, 2026
35cb119
test(network): retain text error semantics on sealed receipts
seonghobae Sep 6, 2026
e567af9
docs: trace text receipt provenance repair and remaining boundaries
seonghobae Sep 6, 2026
716fd84
test(network): replay pointer authority on text response stack
seonghobae Sep 7, 2026
34e537b
fix(network): retain text receipts while adopting pointer safeguards
seonghobae Sep 7, 2026
fcd49b5
docs: record preserved text response and pointer evidence
seonghobae Sep 7, 2026
49d18f5
test: distinguish historical text receipt limitations
seonghobae Sep 7, 2026
ba22e9a
docs: anchor earlier text receipt limitations to predecessor
seonghobae Sep 7, 2026
ff27220
docs: link later pointer adoption evidence directly
seonghobae Sep 7, 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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to OriginWeave are documented in this file. The format follo

## [Unreleased]

- Label earlier text-reply limitations as historical so they do not contradict the later click safeguards.
- Preserve text-reply checks while adopting click-session and reply safeguards. A matched response still does not prove the requested field changed.
- Reject text-entry replies received on a replacement connection without losing the original pending request. The original connection can still complete it; a reply alone does not prove the field changed.
- Text-entry replies cannot complete another kind of pending browser request. Malformed and unrelated replies preserve pending work; acknowledgment alone still does not prove the field changed or authenticate the reply's connection.
- Preserve text-entry safeguards while rejecting clicks sent to another browser session and click replies from replacement connections. These checks do not yet verify that the browser changed the requested field.
- Retain each pending text-entry request's original connection so a connection-aware response consumer can reject replies from a replacement socket. Consumer integration and observed field-value verification remain separate requirements.
- Text entry rejects a connection for a different browser session and invalid deadlines before reserving a pending request. Rejected writes that provably sent nothing release that request; uncertain writes remain pending and are not silently retried. Real-browser outcome verification remains unfinished.
Expand Down
4 changes: 4 additions & 0 deletions crates/originweave-network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ mod webdriver_bidi_session_end_response;
mod webdriver_bidi_session_status_command;
mod webdriver_bidi_session_status_response;
mod webdriver_bidi_session_teardown;
mod webdriver_bidi_type_text_response;
mod webdriver_bidi_type_text_transport;
mod webdriver_bidi_websocket_frame;
mod webdriver_bidi_websocket_handshake;
Expand Down Expand Up @@ -145,6 +146,9 @@ pub use webdriver_bidi_session_teardown::{
WebDriverBiDiSessionTeardownAssessment, WebDriverBiDiSessionTeardownAssessmentError,
WebDriverBiDiSessionTeardownDisposition, WebDriverBiDiSessionTeardownObservations,
};
pub use webdriver_bidi_type_text_response::{
WebDriverBiDiTypeTextResponseError, WebDriverBiDiTypeTextResult,
};
pub use webdriver_bidi_type_text_transport::{
WebDriverBiDiTypeTextSendError, send_webdriver_bidi_type_text,
};
Expand Down
143 changes: 143 additions & 0 deletions crates/originweave-network/src/webdriver_bidi_type_text_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use std::{error::Error, fmt};

use crate::{
WebDriverBiDiCommandCorrelation, WebDriverBiDiCommandCorrelationError,
WebDriverBiDiCommandKind, WebDriverBiDiCorrelatedResponseOutcome, WebDriverBiDiJsonEnvelope,
WebDriverBiDiJsonEnvelopeError, WebDriverBiDiReceivedTextMessage,
};

/// Typed protocol acknowledgment for one correlated WebDriver BiDi `input.performActions`
/// node-bound text-input command.
///
/// The WebDriver BiDi `input.performActions` command returns the extensible `EmptyResult` shape.
/// The common local-end envelope parser already validates the complete JSON document and requires a
/// success `result` object, so this command-specific boundary intentionally retains no generic
/// result body and accepts extension members. This value proves only that the remote end returned a
/// correlated protocol success; it does not prove that the target received text, that a DOM or
/// accessibility state changed, or that any other OriginWeave post-condition was observed.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WebDriverBiDiTypeTextResult {
command_id: u64,
}

impl WebDriverBiDiTypeTextResult {
/// Parse one bounded local-end message and consume its exact outstanding command on response.
///
/// Complete JSON and common WebDriver BiDi envelope validation occur before correlation state
/// can be consumed. Successful responses retain only the matched command id. A correlatable
/// protocol-error response consumes its matching id and returns a typed remote failure, while
/// events, null-id errors, malformed envelopes, and unknown ids fail closed without consuming
/// unrelated outstanding state. Both success and error replies must match the registered
/// text-input command family and the sender's exact connection generation. Missing or
/// mismatched receipt provenance leaves the pending command untouched.
pub fn parse_and_correlate(
message: &WebDriverBiDiReceivedTextMessage,
correlation: &mut WebDriverBiDiCommandCorrelation,
) -> Result<Self, WebDriverBiDiTypeTextResponseError> {
let envelope = WebDriverBiDiJsonEnvelope::parse(message.message())
.map_err(|source| WebDriverBiDiTypeTextResponseError::Envelope { source })?;
let completed = correlation
.correlate_response_for_connection(
&envelope,
WebDriverBiDiCommandKind::TypeText,
message.connection_generation(),
)
.map_err(|source| WebDriverBiDiTypeTextResponseError::Correlation { source })?;

match completed.outcome() {
WebDriverBiDiCorrelatedResponseOutcome::Success => Ok(Self {
command_id: completed.command_id(),
}),
WebDriverBiDiCorrelatedResponseOutcome::Error => {
Err(WebDriverBiDiTypeTextResponseError::RemoteProtocolError {
command_id: completed.command_id(),
})
}
}
}

/// Return the exact local command identifier consumed by this protocol acknowledgment.
#[must_use]
pub const fn command_id(&self) -> u64 {
self.command_id
}
}

/// Fail-closed failures while admitting one typed WebDriver BiDi text-input response.
#[derive(Debug)]
pub enum WebDriverBiDiTypeTextResponseError {
/// Common local-end JSON envelope validation failed before correlation state was touched.
Envelope {
/// Exact common-envelope validation failure.
source: WebDriverBiDiJsonEnvelopeError,
},
/// Exact command-response correlation failed without consuming unrelated state.
Correlation {
/// Exact typed correlation failure.
source: WebDriverBiDiCommandCorrelationError,
},
/// The remote end returned a correlatable WebDriver BiDi protocol error for this command.
RemoteProtocolError {
/// Exact local command identifier consumed by the protocol-error response.
command_id: u64,
},
}

impl fmt::Display for WebDriverBiDiTypeTextResponseError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Envelope { .. } => {
formatter.write_str("WebDriver BiDi text-input envelope is invalid")
}
Self::Correlation { .. } => {
formatter.write_str("WebDriver BiDi text-input response correlation failed")
}
Self::RemoteProtocolError { .. } => {
formatter.write_str("WebDriver BiDi text-input returned a protocol error")
}
}
}
}

impl Error for WebDriverBiDiTypeTextResponseError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Envelope { source } => Some(source),
Self::Correlation { source } => Some(source),
Self::RemoteProtocolError { .. } => None,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn response_errors_have_stable_messages_and_typed_sources() {
let envelope = WebDriverBiDiTypeTextResponseError::Envelope {
source: WebDriverBiDiJsonEnvelopeError::InvalidJson,
};
assert_eq!(
envelope.to_string(),
"WebDriver BiDi text-input envelope is invalid"
);
assert!(envelope.source().is_some());

let correlation = WebDriverBiDiTypeTextResponseError::Correlation {
source: WebDriverBiDiCommandCorrelationError::CommandNotOutstanding,
};
assert_eq!(
correlation.to_string(),
"WebDriver BiDi text-input response correlation failed"
);
assert!(correlation.source().is_some());

let remote = WebDriverBiDiTypeTextResponseError::RemoteProtocolError { command_id: 42 };
assert_eq!(
remote.to_string(),
"WebDriver BiDi text-input returned a protocol error"
);
assert!(remote.source().is_none());
}
}
Loading
Loading