Repository navigation
feat(network): bind typed transport evidence to BiDi teardown #255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
seonghobae
wants to merge
127
commits into
feat/webdriver-bidi-session-end-response
Choose a base branch
from
feat/webdriver-bidi-teardown-transport-binding
base: feat/webdriver-bidi-session-end-response
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 44 commits
Commits
Show all changes
127 commits
Select commit
Hold shift + click to select a range
77aa507
test(network): require operational teardown assessment
seonghobae b5396ee
test(network): format teardown assessment regression
seonghobae 7b0880a
feat(network): separate protocol ack from teardown evidence
seonghobae 1dbf3a8
feat(network): expose teardown assessment boundary
seonghobae bfd2044
test(network): require every teardown observation
seonghobae 0fff981
test(network): require typed BiDi transport closure evidence
seonghobae 4bc7c3c
style(network): apply canonical transport-close test formatting
seonghobae 916f6d4
feat(network): observe typed BiDi transport closure
seonghobae eed38a3
feat(network): export bounded BiDi transport closure evidence
seonghobae 69cfe4c
style(network): apply canonical transport-closure formatting
seonghobae 6612af7
test(network): satisfy strict transport-closure contracts
seonghobae fa68bb9
test(network): cover fail-closed transport closure errors
seonghobae c691d07
chore(network): converge teardown evidence on current session.end res…
seonghobae 5654d0c
chore(network): converge transport closure on current teardown stack
seonghobae f956341
test(network): require pong-tolerant BiDi transport close
seonghobae 80f5000
fix(network): tolerate bounded pong before BiDi transport close
seonghobae 01cfce2
test(network): bound pong handling during BiDi transport close
seonghobae a45812d
style(network): apply canonical rustfmt to transport close tests
seonghobae 5ff8ae1
test(network): require typed transport evidence for BiDi teardown
seonghobae baba701
style(network): apply canonical rustfmt to typed teardown regression
seonghobae 4d43cba
feat(network): bind typed transport closure to teardown
seonghobae 7d72370
style(network): apply canonical teardown formatting
seonghobae ef1b4a9
test(network): reject forgeable teardown completion
seonghobae 72449de
fix(network): fail closed on teardown placeholders
seonghobae ce7c40e
test(network): reject process profile teardown placeholders
seonghobae 43c9ae7
fix(network): remove forgeable teardown placeholders
seonghobae cf5fd42
fix(network): restack teardown assessment on typed session.end
seonghobae 2a93e7e
merge(network): restack transport closure on typed session.end
seonghobae b1712b8
merge(network): restack teardown binding on typed transport closure
seonghobae 964c5b1
merge(network): restack teardown evidence on repaired status response
seonghobae cb49cda
merge(network): restack transport closure on repaired status response
seonghobae 626026c
fix(network): repair typed teardown exact-head regression
seonghobae 88e68f3
fix(network): encode validated BiDi response routing structurally
seonghobae ab1dea7
docs(doctoring): refresh WebDriver BiDi published baseline
seonghobae 870cb39
fix(network): make BiDi response routing structurally valid
seonghobae 4c112e7
merge(parent): refresh teardown evidence base
seonghobae 463859f
merge(parent): refresh transport closure base
seonghobae d60e986
merge(parent): refresh teardown transport binding base
seonghobae 5e2b17c
merge(parent): refresh teardown evidence base
seonghobae a484101
merge(parent): refresh transport close evidence base
seonghobae f8edec3
merge(parent): refresh teardown transport binding base
seonghobae 0d72082
merge: restack teardown evidence on current response
seonghobae cbaf50d
merge: restack transport close on teardown evidence
seonghobae a13de5f
merge: restack teardown binding on close evidence
seonghobae f816be5
test(network): reject cross-connection teardown closure evidence
seonghobae f1f9664
fix(network): fail closed on connection-generation exhaustion
seonghobae fc61df5
fix(network): mint non-forgeable BiDi connection generations
seonghobae c7ce08a
test(network): cover BiDi connection-generation allocator
seonghobae ef62a4e
fix(network): retain connection provenance in BiDi correlation
seonghobae 04f066c
fix(network): bind session.end correlation to exact connection
seonghobae 54265a2
fix(network): bind session.end acknowledgments to connection provenance
seonghobae 8a1b9ee
test(network): require session.end transport provenance
seonghobae dddb93c
fix(network): retain exact connection on transport closure evidence
seonghobae 9452fc3
fix(network): reject teardown evidence from another connection
seonghobae 77b294a
test(network): verify exact transport generation at teardown
seonghobae 23eea66
fix(network): expose teardown provenance mismatch error
seonghobae 92392b2
test(network): cover same-session reconnect and cross-session teardow…
seonghobae 4bb85c2
test(network): prove same-endpoint reconnect provenance isolation
seonghobae ae6495e
refactor(network): type BiDi connection-generation provenance
seonghobae 9115fd8
test(network): type connection-generation allocator evidence
seonghobae ddc1082
refactor(network): carry typed BiDi generation through correlation
seonghobae 2b77143
refactor(network): type session.end connection provenance
seonghobae 4255eb4
refactor(network): type transport-closure connection provenance
seonghobae 0a94765
test(network): reproduce foreign BiDi response correlation
seonghobae 1c2749e
feat(network): bind received BiDi messages to connection
seonghobae 256f6b3
fix(network): reject foreign BiDi response transports
seonghobae 9037db8
fix(network): require received connection provenance for session.end
seonghobae b35a248
feat(network): expose connection-bound BiDi message reader
seonghobae 98fe192
test(network): bind session.end responses to receive stream
seonghobae d4cd2de
test(network): assert exact received transport mismatch
seonghobae ccefd01
refactor(network): return transport after complete BiDi message
seonghobae 59e92c6
test(network): preserve transport through bound response read
seonghobae e7bfec4
test(network): cover connection-bound message reader
seonghobae f4e18ec
docs(network): trace received BiDi connection provenance
seonghobae feba41f
test(network): cover uncorrelatable connection-bound responses
seonghobae 89e3975
fix(network): satisfy teardown provenance lint
seonghobae 6f6d49f
fix(network): remove impossible BiDi provenance fallback
seonghobae ddfac5b
fix(network): expose generation exhaustion to connection tests
seonghobae 78ffe1c
test(network): cover connection generation exhaustion
seonghobae 8315eed
test(network): activate generation exhaustion coverage
seonghobae defa1a0
test(network): restore session.end response formatting
seonghobae 00e007b
test(network): restore response provenance formatting
seonghobae 2c8e9e2
test(network): restore teardown assessment formatting
seonghobae 64b88e6
docs(network): record BiDi provenance quality-gate repair
seonghobae 63cbca0
docs(network): align provenance note with Rust MSRV
seonghobae ebac126
fix(network): remove unused correlation accessor
seonghobae afb623e
merge: adopt current response in teardown assessment
seonghobae b11b6c9
chore: integrate current teardown parent into closure evidence
seonghobae 3e70574
chore(network): integrate current closure provenance parent
seonghobae 6865faa
chore(stack): bind repaired teardown successor to response base
seonghobae 32b5615
test(network): reject replacement status replies in teardown stack
seonghobae c7ccb0c
merge: preserve teardown provenance while adopting current response p…
seonghobae be85f04
merge(stack): adopt current session-end response parent
seonghobae b97f57e
test(network): reject peer-close-only transport evidence
seonghobae 8d63ec8
test(network): require Pong before bounded close completion
seonghobae 1cb76a6
fix(network): complete bounded WebSocket closing handshake
seonghobae 1376f4c
test(network): complete teardown close fixture
seonghobae 2db547c
Merge remote-tracking branch 'origin/feat/webdriver-bidi-teardown-tra…
seonghobae 4305ff8
style(network): apply rustfmt to close frame
seonghobae 1dcaaf8
fix(network): retain connection-bound response correlation
seonghobae ec16b33
fix(network): restore shared response routing
seonghobae bae183e
test(network): cover teardown mask-key failures
seonghobae f060bf1
test(network): cover peer-close mask-key failure
seonghobae 4a7cc03
test(network): cover bounded pre-close control branch
seonghobae ac5cb34
test(network): cover close timeout validation
seonghobae 2fb1b59
test(network): cover excessive close timeout
seonghobae a17914a
fix(network): separate frame timeout guards
seonghobae 9033fbc
fix(network): make timeout validation exhaustive
seonghobae 2bbdc02
fix(network): avoid timeout guard short circuit
seonghobae 6cdf674
test(network): verify close writer deadline rejection directly
seonghobae 7a88551
test(network): preserve exact close deadline assertions
seonghobae d126242
test(network): exercise complete close writer contract
seonghobae 07ef43e
test(network): synchronize mask rejection peers
seonghobae f8df02e
fix(network): bound the complete closure exchange deadline
seonghobae 292d73b
test(network): verify deadline and protocol paths together
seonghobae 8716b9d
fix(network): reject unassigned protocol close codes
seonghobae 383f157
fix(network): admit bounded repeated closure controls
seonghobae 3a8e6f4
test(network): reuse arrays in repeated control fixtures
seonghobae 10d5e1f
test(network): reject server Close 1010
seonghobae 6b6c90e
fix(network): reject server Close 1010
seonghobae ce4ef71
test(network): require role-specific server Close error
seonghobae 39f054f
fix(network): separate peer Close role error
seonghobae cc3bf6d
test(network): assert typed peer Close role error
seonghobae 30b4587
fix(test): retain peer Close error for assertions
seonghobae 9e51537
fix(test): satisfy strict clippy in Close role regression
seonghobae a437163
test(network): remove duplicate Close role fixture
seonghobae ca49031
test(network): share close-role regression with unit coverage
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
crates/originweave-network/src/webdriver_bidi_session_teardown.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| use crate::{WebDriverBiDiSessionEndResult, WebDriverBiDiWebSocketTransportClosureObservation}; | ||
|
|
||
| /// Fail-closed operational disposition derived from teardown observations. | ||
| /// | ||
| /// The current assessment can report only `OperationalTeardownPending`. Transport closure already | ||
| /// has a typed owner, while browser-process exit and task-profile removal are not represented until | ||
| /// their own typed runtime owners are connected. Missing owner evidence cannot establish operational | ||
| /// completion or grant process, profile, browser, network, policy, secret, or Agent authority. | ||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
| pub enum WebDriverBiDiSessionTeardownDisposition { | ||
| /// Operational teardown is not yet proven by typed observations from every owning boundary. | ||
| OperationalTeardownPending, | ||
| } | ||
|
|
||
| /// Explicit operational observations retained after a correlated WebDriver BiDi `session.end` ack. | ||
| /// | ||
| /// Transport closure is represented by the typed observation produced only by consuming the exact | ||
| /// established WebSocket at its bounded closure-observation boundary. Browser-process exit and task | ||
| /// profile removal are deliberately absent until their own typed runtime owners can supply | ||
| /// non-forgeable evidence. | ||
| #[derive(Debug, Eq, PartialEq)] | ||
| pub struct WebDriverBiDiSessionTeardownObservations { | ||
| transport_closure_observation: Option<WebDriverBiDiWebSocketTransportClosureObservation>, | ||
| } | ||
|
|
||
| impl WebDriverBiDiSessionTeardownObservations { | ||
| /// Construct the typed transport observation retained by this boundary. | ||
| /// | ||
| /// Transport closure cannot be asserted with a caller-supplied boolean. `Some` requires the | ||
| /// typed closure observation returned by the bounded transport owner; `None` keeps teardown | ||
| /// pending. Process and profile state cannot be supplied as placeholders and remain unproven | ||
| /// until their typed runtime owners are connected. | ||
| #[must_use] | ||
| pub const fn new( | ||
| transport_closure_observation: Option<WebDriverBiDiWebSocketTransportClosureObservation>, | ||
| ) -> Self { | ||
| Self { | ||
| transport_closure_observation, | ||
| } | ||
| } | ||
|
|
||
| /// Return whether typed closure evidence for the exact session transport was supplied. | ||
| #[must_use] | ||
| pub const fn transport_closed_observed(&self) -> bool { | ||
| self.transport_closure_observation.is_some() | ||
| } | ||
|
|
||
| /// Borrow the typed transport-closure observation when one was supplied. | ||
| #[must_use] | ||
| pub const fn transport_closure_observation( | ||
| &self, | ||
| ) -> Option<&WebDriverBiDiWebSocketTransportClosureObservation> { | ||
| self.transport_closure_observation.as_ref() | ||
| } | ||
| } | ||
|
|
||
| /// One correlated `session.end` acknowledgment kept separate from operational teardown evidence. | ||
| /// | ||
| /// A protocol acknowledgment alone is never operational completion. Typed transport closure is | ||
| /// retained from the consumed WebSocket, while process/profile evidence remains absent until its | ||
| /// owning runtime boundaries can provide typed observations. Consequently this assessment remains | ||
| /// fail closed in the current dependency-ordered slice. | ||
| #[derive(Debug, Eq, PartialEq)] | ||
| pub struct WebDriverBiDiSessionTeardownAssessment { | ||
| protocol_ack: WebDriverBiDiSessionEndResult, | ||
| observations: WebDriverBiDiSessionTeardownObservations, | ||
| } | ||
|
|
||
| impl WebDriverBiDiSessionTeardownAssessment { | ||
| /// Bind one correlated protocol acknowledgment to separately supplied operational observations. | ||
| #[must_use] | ||
| pub const fn from_protocol_ack( | ||
| protocol_ack: WebDriverBiDiSessionEndResult, | ||
| observations: WebDriverBiDiSessionTeardownObservations, | ||
| ) -> Self { | ||
| Self { | ||
| protocol_ack, | ||
| observations, | ||
| } | ||
| } | ||
|
|
||
| /// Return the exact command id proven by the correlated protocol acknowledgment. | ||
| #[must_use] | ||
| pub const fn command_id(&self) -> u64 { | ||
| self.protocol_ack.command_id() | ||
| } | ||
|
|
||
| /// Borrow the explicit operational observations bound to this assessment. | ||
| #[must_use] | ||
| pub const fn observations(&self) -> &WebDriverBiDiSessionTeardownObservations { | ||
| &self.observations | ||
| } | ||
|
|
||
| /// Return whether typed evidence proves every required operational teardown boundary. | ||
| /// | ||
| /// This is always `false` while typed browser-process-exit and task-profile-removal evidence is | ||
| /// absent from this boundary. | ||
| #[must_use] | ||
| pub const fn is_operationally_complete(&self) -> bool { | ||
| false | ||
| } | ||
|
|
||
| /// Return the fail-closed disposition for the currently supplied observations. | ||
| /// | ||
| /// The current boundary cannot emit an operational-completion disposition because process and | ||
| /// profile cleanup still lack typed owner evidence. | ||
| #[must_use] | ||
| pub const fn disposition(&self) -> WebDriverBiDiSessionTeardownDisposition { | ||
| WebDriverBiDiSessionTeardownDisposition::OperationalTeardownPending | ||
| } | ||
| } | ||
129 changes: 129 additions & 0 deletions
129
crates/originweave-network/src/webdriver_bidi_websocket_transport_closure.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| use std::{error::Error, fmt, time::Duration}; | ||
|
|
||
| use crate::{WebDriverBiDiWebSocketEstablished, WebDriverBiDiWebSocketFrameError}; | ||
|
|
||
| /// Bounded transport-closure condition observed on one consumed WebDriver BiDi WebSocket. | ||
| /// | ||
| /// This classification proves only what the already session-correlated transport itself exposed. | ||
| /// A peer Close frame does not prove browser-process exit or profile cleanup, while peer EOF does | ||
| /// not imply that the RFC 6455 closing handshake completed. | ||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
| pub enum WebDriverBiDiWebSocketTransportClosureKind { | ||
| /// The peer sent one RFC 6455 Close frame that passed the existing strict frame validator. | ||
| PeerCloseFrame, | ||
| /// The peer ended the TCP byte stream cleanly before any new WebSocket frame byte was read. | ||
| PeerEof, | ||
| } | ||
|
|
||
| /// Credential-free observation that one established WebDriver BiDi transport ceased carrying data. | ||
| /// | ||
| /// Construction consumes the established WebSocket, so this value cannot be used to regain the | ||
| /// underlying connection. It records only a validated peer Close status when one was actually | ||
| /// present, or clean TCP EOF before a new frame began. It grants no browser, process, profile, | ||
| /// policy, secret, retry, reconnect, or Agent authority and does not perform a reciprocal Close | ||
| /// handshake. | ||
| #[derive(Debug, Eq, PartialEq)] | ||
| pub struct WebDriverBiDiWebSocketTransportClosureObservation { | ||
| kind: WebDriverBiDiWebSocketTransportClosureKind, | ||
| peer_close_status_code: Option<u16>, | ||
| } | ||
|
|
||
| impl WebDriverBiDiWebSocketTransportClosureObservation { | ||
| /// Consume one established connection and observe one bounded transport-closure condition. | ||
| /// | ||
| /// A validated peer Close frame and zero-byte clean EOF are the only success cases. One | ||
| /// unsolicited Pong may be ignored before that closure signal because Pong requires no client | ||
| /// response; a second Pong, Ping, data frame, partial-frame EOF, timeout, malformed Close, I/O | ||
| /// failure, or integrity failure remains a typed error. This fixed two-read envelope prevents | ||
| /// peer control traffic from extending teardown observation indefinitely and does not invent | ||
| /// masking entropy or outbound authority to answer Ping frames. | ||
| pub fn observe( | ||
| established: WebDriverBiDiWebSocketEstablished, | ||
| frame_timeout: Duration, | ||
| ) -> Result<Self, WebDriverBiDiWebSocketTransportClosureError> { | ||
| Self::observe_frame(established, frame_timeout, true) | ||
| } | ||
|
|
||
| fn observe_frame( | ||
| established: WebDriverBiDiWebSocketEstablished, | ||
| frame_timeout: Duration, | ||
| allow_pong: bool, | ||
| ) -> Result<Self, WebDriverBiDiWebSocketTransportClosureError> { | ||
| match established.read_frame(frame_timeout) { | ||
| Ok((established, frame)) if frame.opcode() == 0xa && allow_pong => { | ||
| Self::observe_frame(established, frame_timeout, false) | ||
| } | ||
| Ok((established, frame)) => { | ||
| if frame.opcode() != 0x8 { | ||
| return Err( | ||
| WebDriverBiDiWebSocketTransportClosureError::UnexpectedFrame { | ||
| opcode: frame.opcode(), | ||
| }, | ||
| ); | ||
| } | ||
| let peer_close_status_code = frame | ||
| .payload() | ||
| .get(..2) | ||
| .map(|bytes| u16::from_be_bytes([bytes[0], bytes[1]])); | ||
| drop(established); | ||
| Ok(Self { | ||
| kind: WebDriverBiDiWebSocketTransportClosureKind::PeerCloseFrame, | ||
| peer_close_status_code, | ||
| }) | ||
| } | ||
| Err(WebDriverBiDiWebSocketFrameError::FrameEnded { bytes_read: 0 }) => Ok(Self { | ||
| kind: WebDriverBiDiWebSocketTransportClosureKind::PeerEof, | ||
| peer_close_status_code: None, | ||
| }), | ||
| Err(source) => Err(WebDriverBiDiWebSocketTransportClosureError::Frame { source }), | ||
| } | ||
| } | ||
|
|
||
| /// Return the exact transport-closure condition that produced this observation. | ||
| #[must_use] | ||
| pub const fn kind(&self) -> WebDriverBiDiWebSocketTransportClosureKind { | ||
| self.kind | ||
| } | ||
|
|
||
| /// Return the validated peer Close status when a Close frame actually carried one. | ||
| #[must_use] | ||
| pub const fn peer_close_status_code(&self) -> Option<u16> { | ||
| self.peer_close_status_code | ||
| } | ||
| } | ||
|
|
||
| /// Fail-closed errors while converting one established BiDi transport into closure evidence. | ||
| #[derive(Debug)] | ||
| pub enum WebDriverBiDiWebSocketTransportClosureError { | ||
| /// The peer sent a valid WebSocket frame that was not an admissible closure signal. | ||
| UnexpectedFrame { | ||
| /// Exact validated RFC 6455 opcode observed instead of an admissible closure signal. | ||
| opcode: u8, | ||
| }, | ||
| /// The existing bounded WebSocket frame reader failed before closure was proven. | ||
| Frame { | ||
| /// Original typed frame failure retained as the causal source. | ||
| source: WebDriverBiDiWebSocketFrameError, | ||
| }, | ||
| } | ||
|
|
||
| impl fmt::Display for WebDriverBiDiWebSocketTransportClosureError { | ||
| fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| match self { | ||
| Self::UnexpectedFrame { .. } => formatter | ||
| .write_str("WebDriver BiDi peer sent non-closure traffic instead of closing"), | ||
| Self::Frame { .. } => { | ||
| formatter.write_str("WebDriver BiDi transport closure could not be observed safely") | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl Error for WebDriverBiDiWebSocketTransportClosureError { | ||
| fn source(&self) -> Option<&(dyn Error + 'static)> { | ||
| match self { | ||
| Self::UnexpectedFrame { .. } => None, | ||
| Self::Frame { source } => Some(source), | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.