Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
b2c458c
test(core): require bounded BiDi response envelope parsing
seonghobae Aug 18, 2026
89bd3db
style(core): apply canonical BiDi parser test formatting
seonghobae Aug 18, 2026
77eb49b
feat(core): parse bounded BiDi response envelopes
seonghobae Aug 18, 2026
9f924d2
feat(core): expose BiDi response envelope parser
seonghobae Aug 18, 2026
addb63f
style(core): apply canonical response parser formatting
seonghobae Aug 18, 2026
eb086b0
test(core): exercise hostile BiDi response JSON grammar
seonghobae Aug 18, 2026
5c8df76
fix(core): satisfy strict BiDi parser clippy
seonghobae Aug 18, 2026
e455fe8
test(core): cover response parser failure edges
seonghobae Aug 18, 2026
9447879
fix(core): remove unreachable parser error edges
seonghobae Aug 18, 2026
d45118b
test(core): respect bounded response admission boundary
seonghobae Aug 18, 2026
1b157ef
test(core): avoid panic-prone admission assertion
seonghobae Aug 18, 2026
67f5ca3
fix(core): remove unreachable parser coverage branches
seonghobae Aug 18, 2026
e65df25
test(core): require parsed BiDi response correlation
seonghobae Aug 18, 2026
e9d90df
test(core): apply canonical BiDi correlation formatting
seonghobae Aug 18, 2026
5481255
feat(core): correlate bounded BiDi response documents
seonghobae Aug 18, 2026
35a9f42
docs(changelog): record bounded BiDi document correlation
seonghobae Aug 18, 2026
e0b502a
test(core): reject unknown WebDriver BiDi error codes
seonghobae Aug 18, 2026
ebc127c
test(core): format WebDriver BiDi error-code RED
seonghobae Aug 18, 2026
99b4f5d
fix(core): define WebDriver BiDi error-code vocabulary
seonghobae Aug 18, 2026
9b85be5
fix(core): wire WebDriver BiDi error-code validator
seonghobae Aug 18, 2026
e815964
fix(core): reject unknown WebDriver BiDi error codes
seonghobae Aug 18, 2026
5b829fe
style(core): apply canonical rustfmt ordering
seonghobae Aug 18, 2026
f5e087d
test(core): cover current BiDi client-window error
seonghobae Aug 18, 2026
4077a79
fix(core): admit current BiDi client-window error
seonghobae Aug 18, 2026
b7e5ba5
test(core): keep BiDi failure regression panic-free
seonghobae Aug 18, 2026
9d39c59
docs(doctoring): record current BiDi error-code contract
seonghobae Aug 18, 2026
0e8414c
test(core): require wire-derived locateNodes result admission
seonghobae Aug 18, 2026
3ad1c5f
style(core): apply canonical wire-result test formatting
seonghobae Aug 18, 2026
ee545e6
feat(core): admit locateNodes nodes from bounded wire response
seonghobae Aug 18, 2026
2f12879
style(core): apply canonical response document formatting
seonghobae Aug 18, 2026
c8d6d9a
style(core): apply canonical wire node parser formatting
seonghobae Aug 18, 2026
e7b81bc
test(core): cover locateNodes document failure boundaries
seonghobae Aug 18, 2026
16591ab
test(core): keep failure-evidence regressions clippy-clean
seonghobae Aug 18, 2026
858bcf4
test(core): cover locateNodes second-pass parser invariants
seonghobae Aug 18, 2026
da7ffe9
test(core): avoid node debug equality requirement
seonghobae Aug 18, 2026
1b0f6ad
style(core): apply canonical wire-result formatting
seonghobae Aug 18, 2026
cbbc4d6
test(core): cover second-pass parser failure propagation
seonghobae Aug 18, 2026
755ba06
fix(core): keep second-pass string decoding utf8-safe
seonghobae Aug 18, 2026
70d85f9
test(core): cover wire node admission tuple
seonghobae Aug 18, 2026
4089a72
test(core): cover skipped wire result shapes
seonghobae Aug 18, 2026
14a4a39
test(core): cover wire node admission metadata
seonghobae Aug 18, 2026
a2fe264
test(core): prioritize locateNodes result budget
seonghobae Aug 18, 2026
3083e4e
fix(core): enforce locateNodes budget before node decoding
seonghobae Aug 18, 2026
6c3b0bd
fix(core): bind wire parsing to exact result budget
seonghobae Aug 18, 2026
850dbf1
test(core): cover bounded overflow parser invariant
seonghobae Aug 18, 2026
e373a73
test(core): close bounded overflow coverage invariant
seonghobae Aug 18, 2026
dfc522f
test(core): require bounded BiDi byte admission
seonghobae Aug 18, 2026
42c0443
feat(core): admit bounded BiDi response bytes
seonghobae Aug 18, 2026
c80ffdb
test(core): require typed BiDi error-code evidence
seonghobae Aug 18, 2026
f331b32
style(core): canonicalize error-code RED
seonghobae Aug 18, 2026
e9f4dcc
fix(core): retain typed BiDi error-code evidence
seonghobae Aug 18, 2026
358c6e2
test(core): prove every typed BiDi error mapping
seonghobae Aug 18, 2026
6740339
fix(core): restore canonical Rust formatting
seonghobae Aug 18, 2026
a451054
test(core): require wire-to-authority node binding
seonghobae Aug 18, 2026
bcc719f
test(core): format wire authority regression
seonghobae Aug 18, 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes to OriginWeave are documented in this file. The format follo
- Fail-closed WebDriver BiDi `locateNodes` response correlation that consumes the exact serialized command, rejects out-of-range or mismatched response `id` values, and returns non-cloneable correlation evidence carrying only the matched command identifier and browsing context without parsing the response or granting browser/Agent authority.
- Typed WebDriver BiDi response-envelope correlation that preserves success/error classification, rejects success responses with absent ids, treats nullable error ids as explicitly uncorrelatable, and prevents correlated error envelopes from becoming success correlation evidence without raw JSON parsing or browser/Agent authority grants.
- Bounded raw WebDriver BiDi response-document admission before JSON parsing, with a 65,536-byte product safety budget, exact wire-text retention, JSON-whitespace-aware top-level object-boundary checks, and typed fail-closed errors; this coarse boundary deliberately does not claim JSON validity, response correlation, browser authenticity, or Agent authority.
- One consuming bounded WebDriver BiDi response-document correlation boundary that parses the exact admitted JSON document and feeds only its typed response kind and protocol-range id into the existing exact command-correlation gate, preserving nested parser/correlation error sources without authenticating transport or granting browser/Agent authority.
- Fail-closed WebDriver BiDi `script.NodeRemoteValue` admission that requires the exact remote type `node` and a non-empty `sharedId` within the same UTF-8 identifier budget as browser session and context identifiers, rejecting control and whitespace so an untrusted `locateNodes` item cannot be retained as a later typed-input handle without a usable shared node identity.
- Same-call `locateNodes` result admission that revalidates the exact current session, browsing context, canonical origin, and document epoch, rejects an over-budget or non-node result, and translates each admitted `sharedId` through the authority registry into an `ObservedNodeHandle` without performing browser I/O.
- Same-call QueryNodes admission that transfers a non-cloneable SemanticObservation protocol-use proof by ownership into `bind_current_nodes` before an untrusted `locateNodes` result can become current `ObservedNodeHandle` values, so Navigation-only or TypedInput-only proofs cannot mint observation handles.
Expand Down
9 changes: 9 additions & 0 deletions crates/originweave-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ mod browser_registry;
mod browser_registry_coverage;
mod contracts;
mod webdriver_bidi_command;
mod webdriver_bidi_error_code;
mod webdriver_bidi_response_document;
mod webdriver_bidi_response_document_correlation;
mod webdriver_bidi_response_envelope;
mod webdriver_bidi_result;

pub use browser_authority_registry::BrowserAuthorityRegistry;
Expand Down Expand Up @@ -71,10 +74,16 @@ pub use webdriver_bidi_command::{
WebDriverBiDiLocateNodesResponseCorrelationError,
WebDriverBiDiLocateNodesResponseEnvelopeError,
};
pub use webdriver_bidi_error_code::WebDriverBiDiErrorCode;
pub use webdriver_bidi_response_document::{
BoundedWebDriverBiDiResponseDocument, MAX_WEBDRIVER_BIDI_RESPONSE_DOCUMENT_BYTES,
WebDriverBiDiResponseDocumentAdmissionError,
};
pub use webdriver_bidi_response_document_correlation::WebDriverBiDiLocateNodesResponseDocumentError;
pub use webdriver_bidi_response_envelope::{
MAX_WEBDRIVER_BIDI_RESPONSE_JSON_DEPTH, MAX_WEBDRIVER_BIDI_RESPONSE_TOP_LEVEL_FIELDS,
ParsedWebDriverBiDiCommandResponseEnvelope, WebDriverBiDiResponseEnvelopeParseError,
};
pub use webdriver_bidi_result::{
ValidatedWebDriverBiDiLocateNodesResult, WebDriverBiDiLocateNodesResultAdmissionError,
};
170 changes: 170 additions & 0 deletions crates/originweave-core/src/webdriver_bidi_error_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/// Typed current WebDriver BiDi protocol error code retained from one validated error response.
///
/// This vocabulary is deliberately closed over the protocol error codes reviewed by OriginWeave.
/// Unknown wire text remains fail-closed and cannot become typed protocol evidence.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WebDriverBiDiErrorCode {
/// The command or one of its arguments is invalid.
InvalidArgument,
/// A selector argument is invalid.
InvalidSelector,
/// The referenced browser session does not exist.
InvalidSessionId,
/// The referenced web extension is invalid.
InvalidWebExtension,
/// A requested pointer move target is outside the allowed bounds.
MoveTargetOutOfBounds,
/// The referenced user prompt does not exist.
NoSuchAlert,
/// The referenced client window does not exist.
NoSuchClientWindow,
/// The referenced network collector does not exist.
NoSuchNetworkCollector,
/// The referenced element does not exist.
NoSuchElement,
/// The referenced frame does not exist.
NoSuchFrame,
/// The referenced handle does not exist.
NoSuchHandle,
/// The referenced history entry does not exist.
NoSuchHistoryEntry,
/// The referenced network intercept does not exist.
NoSuchIntercept,
/// The requested network data does not exist.
NoSuchNetworkData,
/// The referenced node does not exist.
NoSuchNode,
/// The referenced network request does not exist.
NoSuchRequest,
/// The referenced screencast does not exist.
NoSuchScreencast,
/// The referenced script does not exist.
NoSuchScript,
/// The referenced storage partition does not exist.
NoSuchStoragePartition,
/// The referenced user context does not exist.
NoSuchUserContext,
/// The referenced web extension does not exist.
NoSuchWebExtension,
/// A browser session could not be created.
SessionNotCreated,
/// The browser could not capture the requested screen image.
UnableToCaptureScreen,
/// The browser could not close as requested.
UnableToCloseBrowser,
/// The browser could not set the requested cookie.
UnableToSetCookie,
/// The browser could not set the requested file input.
UnableToSetFileInput,
/// Requested network data is temporarily unavailable.
UnavailableNetworkData,
/// The supplied storage-partition descriptor is underspecified.
UnderspecifiedStoragePartition,
/// The command is unknown to the remote end.
UnknownCommand,
/// The remote end reported an otherwise unclassified protocol error.
UnknownError,
/// The requested operation is unsupported by the remote end.
UnsupportedOperation,
}

/// Parse one exact decoded WebDriver BiDi `ErrorCode` value into typed protocol evidence.
pub(crate) fn parse_webdriver_bidi_error_code(value: &[u8]) -> Option<WebDriverBiDiErrorCode> {
const ERROR_CODES: &[(&[u8], WebDriverBiDiErrorCode)] = &[
(b"invalid argument", WebDriverBiDiErrorCode::InvalidArgument),
(b"invalid selector", WebDriverBiDiErrorCode::InvalidSelector),
(
b"invalid session id",
WebDriverBiDiErrorCode::InvalidSessionId,
),
(
b"invalid web extension",
WebDriverBiDiErrorCode::InvalidWebExtension,
),
(
b"move target out of bounds",
WebDriverBiDiErrorCode::MoveTargetOutOfBounds,
),
(b"no such alert", WebDriverBiDiErrorCode::NoSuchAlert),
(
b"no such client window",
WebDriverBiDiErrorCode::NoSuchClientWindow,
),
(
b"no such network collector",
WebDriverBiDiErrorCode::NoSuchNetworkCollector,
),
(b"no such element", WebDriverBiDiErrorCode::NoSuchElement),
(b"no such frame", WebDriverBiDiErrorCode::NoSuchFrame),
(b"no such handle", WebDriverBiDiErrorCode::NoSuchHandle),
(
b"no such history entry",
WebDriverBiDiErrorCode::NoSuchHistoryEntry,
),
(
b"no such intercept",
WebDriverBiDiErrorCode::NoSuchIntercept,
),
(
b"no such network data",
WebDriverBiDiErrorCode::NoSuchNetworkData,
),
(b"no such node", WebDriverBiDiErrorCode::NoSuchNode),
(b"no such request", WebDriverBiDiErrorCode::NoSuchRequest),
(
b"no such screencast",
WebDriverBiDiErrorCode::NoSuchScreencast,
),
(b"no such script", WebDriverBiDiErrorCode::NoSuchScript),
(
b"no such storage partition",
WebDriverBiDiErrorCode::NoSuchStoragePartition,
),
(
b"no such user context",
WebDriverBiDiErrorCode::NoSuchUserContext,
),
(
b"no such web extension",
WebDriverBiDiErrorCode::NoSuchWebExtension,
),
(
b"session not created",
WebDriverBiDiErrorCode::SessionNotCreated,
),
(
b"unable to capture screen",
WebDriverBiDiErrorCode::UnableToCaptureScreen,
),
(
b"unable to close browser",
WebDriverBiDiErrorCode::UnableToCloseBrowser,
),
(
b"unable to set cookie",
WebDriverBiDiErrorCode::UnableToSetCookie,
),
(
b"unable to set file input",
WebDriverBiDiErrorCode::UnableToSetFileInput,
),
(
b"unavailable network data",
WebDriverBiDiErrorCode::UnavailableNetworkData,
),
(
b"underspecified storage partition",
WebDriverBiDiErrorCode::UnderspecifiedStoragePartition,
),
(b"unknown command", WebDriverBiDiErrorCode::UnknownCommand),
(b"unknown error", WebDriverBiDiErrorCode::UnknownError),
(
b"unsupported operation",
WebDriverBiDiErrorCode::UnsupportedOperation,
),
];

ERROR_CODES
.iter()
.find_map(|(raw, code)| (*raw == value).then_some(*code))
}
22 changes: 22 additions & 0 deletions crates/originweave-core/src/webdriver_bidi_response_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub enum WebDriverBiDiResponseDocumentAdmissionError {
EmptyDocument,
/// The raw response exceeds the OriginWeave pre-parser byte budget.
DocumentTooLarge,
/// The raw response is not valid UTF-8.
InvalidUtf8,
/// The first and last non-whitespace bytes do not delimit a JSON object.
InvalidObjectBoundary,
}
Expand All @@ -27,6 +29,9 @@ impl fmt::Display for WebDriverBiDiResponseDocumentAdmissionError {
formatter,
"WebDriver BiDi response document exceeds {MAX_WEBDRIVER_BIDI_RESPONSE_DOCUMENT_BYTES} bytes"
),
Self::InvalidUtf8 => {
formatter.write_str("WebDriver BiDi response document is not valid UTF-8")
}
Self::InvalidObjectBoundary => formatter.write_str(
"WebDriver BiDi response document must have a top-level JSON object boundary",
),
Expand Down Expand Up @@ -68,6 +73,23 @@ impl BoundedWebDriverBiDiResponseDocument {
})
}

/// Admits raw transport bytes after bounding them and validating UTF-8.
///
/// The byte budget is checked before UTF-8 validation or owned-text
/// allocation. This keeps hostile transport payloads outside the parser
/// boundary until both the resource and text-encoding contracts hold.
pub fn from_utf8_bytes(
raw: &[u8],
) -> Result<Self, WebDriverBiDiResponseDocumentAdmissionError> {
if raw.len() > MAX_WEBDRIVER_BIDI_RESPONSE_DOCUMENT_BYTES {
return Err(WebDriverBiDiResponseDocumentAdmissionError::DocumentTooLarge);
}

let raw = std::str::from_utf8(raw)
.map_err(|_| WebDriverBiDiResponseDocumentAdmissionError::InvalidUtf8)?;
Self::new(raw)
}

/// Returns the exact admitted response text, including surrounding JSON whitespace.
#[must_use]
pub fn as_str(&self) -> &str {
Expand Down
Loading
Loading