From 2e0404e34cc0088bab18d6790bbaa32003624171 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:36:22 +0900 Subject: [PATCH 01/10] test(core): require same-call browser protocol dispatch validation --- .../browser_protocol_runtime_dispatch.rs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs diff --git a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs new file mode 100644 index 000000000..168c25758 --- /dev/null +++ b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs @@ -0,0 +1,94 @@ +use std::{cell::Cell, error::Error}; + +use originweave_core::{ + BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, + BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, +}; + +const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion = + OriginWeaveProtocolVersion::new(0, 1); +const ADAPTER_VERSION: &str = "originweave-bidi-v1"; +const PROTOCOL_REVISION: &str = "webdriver-bidi-wd-2026-06-01"; +const BROWSER_REVISION: &str = "chromium-r1639810"; + +fn descriptor() -> Result> { + Ok(BrowserProtocolAdapterDescriptor::new( + BrowserProtocolKind::WebDriverBiDi, + ORIGINWEAVE_PROTOCOL_VERSION, + ADAPTER_VERSION, + PROTOCOL_REVISION, + BROWSER_REVISION, + &[BrowserProtocolCapability::Navigation], + )?) +} + +#[test] +fn exact_runtime_validation_hands_single_use_proof_to_dispatch() -> Result<(), Box> { + let descriptor = descriptor()?; + let called = Cell::new(false); + + let output = descriptor.dispatch_if_runtime_matches( + ORIGINWEAVE_PROTOCOL_VERSION, + BrowserProtocolKind::WebDriverBiDi, + ADAPTER_VERSION, + PROTOCOL_REVISION, + BROWSER_REVISION, + BrowserProtocolCapability::Navigation, + |validated| { + called.set(true); + ( + validated.adapter_version().to_owned(), + validated.capability(), + ) + }, + )?; + + assert!(called.get()); + assert_eq!(output.0, ADAPTER_VERSION); + assert_eq!(output.1, BrowserProtocolCapability::Navigation); + Ok(()) +} + +#[test] +fn runtime_mismatch_prevents_dispatch_callback() -> Result<(), Box> { + let descriptor = descriptor()?; + let called = Cell::new(false); + + let result = descriptor.dispatch_if_runtime_matches( + ORIGINWEAVE_PROTOCOL_VERSION, + BrowserProtocolKind::WebDriverBiDi, + "originweave-bidi-v2", + PROTOCOL_REVISION, + BROWSER_REVISION, + BrowserProtocolCapability::Navigation, + |_| { + called.set(true); + "dispatched" + }, + ); + + assert_eq!( + result, + Err(BrowserProtocolUseValidationError::AdapterVersionMismatch) + ); + assert!(!called.get()); + Ok(()) +} + +#[test] +fn adapter_callback_failure_remains_separate_after_validation() -> Result<(), Box> { + let descriptor = descriptor()?; + + let dispatch_result = descriptor.dispatch_if_runtime_matches( + ORIGINWEAVE_PROTOCOL_VERSION, + BrowserProtocolKind::WebDriverBiDi, + ADAPTER_VERSION, + PROTOCOL_REVISION, + BROWSER_REVISION, + BrowserProtocolCapability::Navigation, + |_| Err::<(), _>("adapter-failure"), + )?; + + assert_eq!(dispatch_result, Err("adapter-failure")); + Ok(()) +} From decc241c7fd6311d4eebb5a5f43b3cec281f994b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:40:19 +0900 Subject: [PATCH 02/10] test(core): share dispatch callback monomorphization --- .../browser_protocol_runtime_dispatch.rs | 76 +++++++++++++------ 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs index 168c25758..6208be11b 100644 --- a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs +++ b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs @@ -1,8 +1,9 @@ use std::{cell::Cell, error::Error}; use originweave_core::{ - BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, - BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, + dispatch_browser_protocol_if_runtime_matches, BrowserProtocolAdapterDescriptor, + BrowserProtocolCapability, BrowserProtocolKind, BrowserProtocolUseValidationError, + OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, }; const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion = @@ -11,6 +12,13 @@ const ADAPTER_VERSION: &str = "originweave-bidi-v1"; const PROTOCOL_REVISION: &str = "webdriver-bidi-wd-2026-06-01"; const BROWSER_REVISION: &str = "chromium-r1639810"; +type DispatchOutcome = Result<(String, BrowserProtocolCapability), &'static str>; +type DispatchFn = fn(ValidatedBrowserProtocolUse) -> DispatchOutcome; + +thread_local! { + static DISPATCH_CALLED: Cell = const { Cell::new(false) }; +} + fn descriptor() -> Result> { Ok(BrowserProtocolAdapterDescriptor::new( BrowserProtocolKind::WebDriverBiDi, @@ -22,73 +30,95 @@ fn descriptor() -> Result> { )?) } +fn reset_dispatch_marker() { + DISPATCH_CALLED.with(|called| called.set(false)); +} + +fn dispatch_was_called() -> bool { + DISPATCH_CALLED.with(Cell::get) +} + +fn successful_dispatch(validated: ValidatedBrowserProtocolUse) -> DispatchOutcome { + DISPATCH_CALLED.with(|called| called.set(true)); + Ok(( + validated.adapter_version().to_owned(), + validated.capability(), + )) +} + +fn failing_dispatch(_: ValidatedBrowserProtocolUse) -> DispatchOutcome { + DISPATCH_CALLED.with(|called| called.set(true)); + Err("adapter-failure") +} + #[test] fn exact_runtime_validation_hands_single_use_proof_to_dispatch() -> Result<(), Box> { let descriptor = descriptor()?; - let called = Cell::new(false); + reset_dispatch_marker(); - let output = descriptor.dispatch_if_runtime_matches( + let dispatch_result = dispatch_browser_protocol_if_runtime_matches( + &descriptor, ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, ADAPTER_VERSION, PROTOCOL_REVISION, BROWSER_REVISION, BrowserProtocolCapability::Navigation, - |validated| { - called.set(true); - ( - validated.adapter_version().to_owned(), - validated.capability(), - ) - }, + successful_dispatch as DispatchFn, )?; - assert!(called.get()); - assert_eq!(output.0, ADAPTER_VERSION); - assert_eq!(output.1, BrowserProtocolCapability::Navigation); + assert!(dispatch_was_called()); + assert_eq!( + dispatch_result, + Ok(( + ADAPTER_VERSION.to_owned(), + BrowserProtocolCapability::Navigation + )) + ); Ok(()) } #[test] fn runtime_mismatch_prevents_dispatch_callback() -> Result<(), Box> { let descriptor = descriptor()?; - let called = Cell::new(false); + reset_dispatch_marker(); - let result = descriptor.dispatch_if_runtime_matches( + let result = dispatch_browser_protocol_if_runtime_matches( + &descriptor, ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, "originweave-bidi-v2", PROTOCOL_REVISION, BROWSER_REVISION, BrowserProtocolCapability::Navigation, - |_| { - called.set(true); - "dispatched" - }, + successful_dispatch as DispatchFn, ); assert_eq!( result, Err(BrowserProtocolUseValidationError::AdapterVersionMismatch) ); - assert!(!called.get()); + assert!(!dispatch_was_called()); Ok(()) } #[test] fn adapter_callback_failure_remains_separate_after_validation() -> Result<(), Box> { let descriptor = descriptor()?; + reset_dispatch_marker(); - let dispatch_result = descriptor.dispatch_if_runtime_matches( + let dispatch_result = dispatch_browser_protocol_if_runtime_matches( + &descriptor, ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, ADAPTER_VERSION, PROTOCOL_REVISION, BROWSER_REVISION, BrowserProtocolCapability::Navigation, - |_| Err::<(), _>("adapter-failure"), + failing_dispatch as DispatchFn, )?; + assert!(dispatch_was_called()); assert_eq!(dispatch_result, Err("adapter-failure")); Ok(()) } From ff5a8015a0174d3d1f011f731c9e1f15a270f2bc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:40:55 +0900 Subject: [PATCH 03/10] feat(core): gate protocol dispatch on current runtime metadata --- .../src/browser_protocol_dispatch.rs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 crates/originweave-core/src/browser_protocol_dispatch.rs diff --git a/crates/originweave-core/src/browser_protocol_dispatch.rs b/crates/originweave-core/src/browser_protocol_dispatch.rs new file mode 100644 index 000000000..b3e62954a --- /dev/null +++ b/crates/originweave-core/src/browser_protocol_dispatch.rs @@ -0,0 +1,39 @@ +use crate::{ + BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, + BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, +}; + +/// Validate current browser-protocol metadata and immediately invoke one dispatch callback. +/// +/// The runtime protocol family, adapter version, protocol revision, and browser revision must be +/// sampled from the trusted adapter that is about to perform the operation. Validation occurs +/// before `dispatch` is invoked, and the callback receives the resulting non-cloneable +/// [`ValidatedBrowserProtocolUse`] by ownership so this boundary does not turn successful +/// validation into reusable ambient authority. +/// +/// A successful callback invocation does not authenticate the adapter process, authorize a browser +/// session, browsing context, origin, destination, secret, or approval, or prove a browser +/// post-condition. Those remain separate higher-level execution boundaries. +pub fn dispatch_browser_protocol_if_runtime_matches( + descriptor: &BrowserProtocolAdapterDescriptor, + required_originweave_protocol_version: OriginWeaveProtocolVersion, + runtime_kind: BrowserProtocolKind, + runtime_adapter_version: &str, + runtime_protocol_revision: &str, + runtime_browser_revision: &str, + required_capability: BrowserProtocolCapability, + dispatch: F, +) -> Result +where + F: FnOnce(ValidatedBrowserProtocolUse) -> R, +{ + let validated = descriptor.validate_use( + required_originweave_protocol_version, + runtime_kind, + runtime_adapter_version, + runtime_protocol_revision, + runtime_browser_revision, + required_capability, + )?; + Ok(dispatch(validated)) +} From d6a84594815d1859e9fb3e9b6883bda3c61f3167 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:41:17 +0900 Subject: [PATCH 04/10] feat(core): expose validated protocol dispatch boundary --- crates/originweave-core/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index bf8f2fa5e..99153aa7c 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -9,6 +9,7 @@ #![deny(missing_docs)] mod browser_protocol; +mod browser_protocol_dispatch; mod browser_registry; #[cfg(test)] mod browser_registry_coverage; @@ -21,6 +22,7 @@ pub use browser_protocol::{ BrowserProtocolVersionRequirementError, MAX_BROWSER_PROTOCOL_METADATA_BYTES, OriginWeaveProtocolVersion, OriginWeaveProtocolVersionParseError, ValidatedBrowserProtocolUse, }; +pub use browser_protocol_dispatch::dispatch_browser_protocol_if_runtime_matches; pub use browser_registry::{ BrowserAuthorityRegistry, BrowserRegistryError, MAX_EXTERNAL_BROWSER_IDENTIFIER_BYTES, }; From 37dc70d5d66465af7d60935f3d50cd8c54ffe7fd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:42:18 +0900 Subject: [PATCH 05/10] docs: record validated protocol dispatch boundary --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b3f92b50..fadbbc8b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Canonical OriginWeave protocol-version parsing for exact `originweave/.` syntax, with typed fail-closed rejection of malformed, ambiguous, overflowed, or noncanonical serialized generations; parsing does not negotiate compatibility or grant adapter authority. - Atomic browser-protocol use validation that requires the exact OriginWeave protocol generation, caller-supplied runtime protocol family, exact pinned runtime protocol/browser revisions, and an explicitly declared capability in deterministic fail-closed order before producing non-cloneable validation evidence; this metadata proof does not authenticate the adapter or grant browser/Agent authority. - Runtime browser-adapter version binding at the atomic protocol-use boundary: the caller-supplied bounded adapter-version token must exactly match the reviewed descriptor version before runtime revision or capability checks can succeed, preventing adapter-build drift from silently reusing otherwise matching protocol/browser metadata without authenticating or attesting the adapter process. +- Same-call browser-protocol dispatch gating that validates current protocol family, adapter version, pinned protocol/browser revisions, OriginWeave generation, and required capability before invoking one callback, transferring the non-cloneable validation proof by ownership without turning metadata validation into browser or Agent authority. - Credential-safe browser-protocol validation evidence that copies only the already validated protocol family, OriginWeave generation, adapter version, pinned protocol/browser revisions, and exact capability into cloneable audit metadata without recreating the non-cloneable validation prerequisite or granting browser/Agent authority. - Canonical HTTPS and loopback-origin boundary with case-normalized schemes and hosts, default-port normalization, IPv4/IPv6 handling, browser-special numeric-host rejection, and explicit malformed-input errors. - Typed browser actions, capabilities, risk classes, execution modes, robots decisions, secret-delivery contracts, immutable canonical action-intent digests, and intent-bound approval scopes. From 1218808104b609de936de02a7844a39075019135 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:44:49 +0900 Subject: [PATCH 06/10] style(core): apply canonical dispatch test formatting --- .../tests/browser_protocol_runtime_dispatch.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs index 6208be11b..28c575606 100644 --- a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs +++ b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs @@ -1,9 +1,9 @@ use std::{cell::Cell, error::Error}; use originweave_core::{ - dispatch_browser_protocol_if_runtime_matches, BrowserProtocolAdapterDescriptor, - BrowserProtocolCapability, BrowserProtocolKind, BrowserProtocolUseValidationError, - OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, + BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, + BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, + dispatch_browser_protocol_if_runtime_matches, }; const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion = From 3c23d10640ba48e416bf1dfcddef419e18ebdeab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:45:50 +0900 Subject: [PATCH 07/10] refactor(core): make validated dispatch an adapter descriptor method --- .../src/browser_protocol_dispatch.rs | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/crates/originweave-core/src/browser_protocol_dispatch.rs b/crates/originweave-core/src/browser_protocol_dispatch.rs index b3e62954a..d11245f84 100644 --- a/crates/originweave-core/src/browser_protocol_dispatch.rs +++ b/crates/originweave-core/src/browser_protocol_dispatch.rs @@ -3,37 +3,39 @@ use crate::{ BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, }; -/// Validate current browser-protocol metadata and immediately invoke one dispatch callback. -/// -/// The runtime protocol family, adapter version, protocol revision, and browser revision must be -/// sampled from the trusted adapter that is about to perform the operation. Validation occurs -/// before `dispatch` is invoked, and the callback receives the resulting non-cloneable -/// [`ValidatedBrowserProtocolUse`] by ownership so this boundary does not turn successful -/// validation into reusable ambient authority. -/// -/// A successful callback invocation does not authenticate the adapter process, authorize a browser -/// session, browsing context, origin, destination, secret, or approval, or prove a browser -/// post-condition. Those remain separate higher-level execution boundaries. -pub fn dispatch_browser_protocol_if_runtime_matches( - descriptor: &BrowserProtocolAdapterDescriptor, - required_originweave_protocol_version: OriginWeaveProtocolVersion, - runtime_kind: BrowserProtocolKind, - runtime_adapter_version: &str, - runtime_protocol_revision: &str, - runtime_browser_revision: &str, - required_capability: BrowserProtocolCapability, - dispatch: F, -) -> Result -where - F: FnOnce(ValidatedBrowserProtocolUse) -> R, -{ - let validated = descriptor.validate_use( - required_originweave_protocol_version, - runtime_kind, - runtime_adapter_version, - runtime_protocol_revision, - runtime_browser_revision, - required_capability, - )?; - Ok(dispatch(validated)) +impl BrowserProtocolAdapterDescriptor { + /// Validate current browser-protocol metadata and immediately invoke one dispatch callback. + /// + /// The runtime protocol family, adapter version, protocol revision, and browser revision must + /// be sampled from the trusted adapter that is about to perform the operation. Validation + /// occurs before `dispatch` is invoked, and the callback receives the resulting non-cloneable + /// [`ValidatedBrowserProtocolUse`] by ownership so this boundary does not turn successful + /// validation into reusable ambient authority. + /// + /// A successful callback invocation does not authenticate the adapter process, authorize a + /// browser session, browsing context, origin, destination, secret, or approval, or prove a + /// browser post-condition. Those remain separate higher-level execution boundaries. + pub fn dispatch_if_runtime_matches( + &self, + required_originweave_protocol_version: OriginWeaveProtocolVersion, + runtime_kind: BrowserProtocolKind, + runtime_adapter_version: &str, + runtime_protocol_revision: &str, + runtime_browser_revision: &str, + required_capability: BrowserProtocolCapability, + dispatch: F, + ) -> Result + where + F: FnOnce(ValidatedBrowserProtocolUse) -> R, + { + let validated = self.validate_use( + required_originweave_protocol_version, + runtime_kind, + runtime_adapter_version, + runtime_protocol_revision, + runtime_browser_revision, + required_capability, + )?; + Ok(dispatch(validated)) + } } From 043ea96a7a5803bb60f9ceab19cc620684a38de7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:46:08 +0900 Subject: [PATCH 08/10] refactor(core): keep dispatch method on adapter descriptor --- crates/originweave-core/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index 99153aa7c..70cafa890 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -22,7 +22,6 @@ pub use browser_protocol::{ BrowserProtocolVersionRequirementError, MAX_BROWSER_PROTOCOL_METADATA_BYTES, OriginWeaveProtocolVersion, OriginWeaveProtocolVersionParseError, ValidatedBrowserProtocolUse, }; -pub use browser_protocol_dispatch::dispatch_browser_protocol_if_runtime_matches; pub use browser_registry::{ BrowserAuthorityRegistry, BrowserRegistryError, MAX_EXTERNAL_BROWSER_IDENTIFIER_BYTES, }; From 570b4d055ee9b24e7d9dfa82d824fcf023911912 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:48:21 +0900 Subject: [PATCH 09/10] test(core): dispatch through adapter descriptor method --- .../tests/browser_protocol_runtime_dispatch.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs index 28c575606..a16334fcf 100644 --- a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs +++ b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs @@ -3,7 +3,6 @@ use std::{cell::Cell, error::Error}; use originweave_core::{ BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, - dispatch_browser_protocol_if_runtime_matches, }; const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion = @@ -56,8 +55,7 @@ fn exact_runtime_validation_hands_single_use_proof_to_dispatch() -> Result<(), B let descriptor = descriptor()?; reset_dispatch_marker(); - let dispatch_result = dispatch_browser_protocol_if_runtime_matches( - &descriptor, + let dispatch_result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, ADAPTER_VERSION, @@ -83,8 +81,7 @@ fn runtime_mismatch_prevents_dispatch_callback() -> Result<(), Box> { let descriptor = descriptor()?; reset_dispatch_marker(); - let result = dispatch_browser_protocol_if_runtime_matches( - &descriptor, + let result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, "originweave-bidi-v2", @@ -107,8 +104,7 @@ fn adapter_callback_failure_remains_separate_after_validation() -> Result<(), Bo let descriptor = descriptor()?; reset_dispatch_marker(); - let dispatch_result = dispatch_browser_protocol_if_runtime_matches( - &descriptor, + let dispatch_result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, BrowserProtocolKind::WebDriverBiDi, ADAPTER_VERSION, From 9fd91db4d75dfa0db714605d1248f399d0fc6428 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 12 Aug 2026 17:53:44 +0900 Subject: [PATCH 10/10] refactor(core): bind dispatch to bounded runtime metadata --- .../src/browser_protocol_dispatch.rs | 56 ++++++++++++++----- crates/originweave-core/src/lib.rs | 1 + .../browser_protocol_runtime_dispatch.rs | 27 ++++----- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/crates/originweave-core/src/browser_protocol_dispatch.rs b/crates/originweave-core/src/browser_protocol_dispatch.rs index d11245f84..6664545b3 100644 --- a/crates/originweave-core/src/browser_protocol_dispatch.rs +++ b/crates/originweave-core/src/browser_protocol_dispatch.rs @@ -3,14 +3,47 @@ use crate::{ BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, }; +/// Current runtime metadata sampled from the browser-protocol adapter about to perform I/O. +/// +/// This value is untrusted descriptive input. Constructing it does not validate or authenticate an +/// adapter, browser, or protocol revision and grants no browser or Agent authority. The descriptor +/// validates every field against its reviewed metadata before a dispatch callback can run. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct BrowserProtocolRuntimeMetadata<'a> { + kind: BrowserProtocolKind, + adapter_version: &'a str, + protocol_revision: &'a str, + browser_revision: &'a str, +} + +impl<'a> BrowserProtocolRuntimeMetadata<'a> { + /// Build one runtime metadata snapshot for immediate validation and dispatch. + /// + /// String syntax and descriptor equality are intentionally checked later by + /// [`BrowserProtocolAdapterDescriptor::dispatch_if_runtime_matches`], so malformed caller data + /// remains representable as input that the fail-closed boundary can reject deterministically. + pub const fn new( + kind: BrowserProtocolKind, + adapter_version: &'a str, + protocol_revision: &'a str, + browser_revision: &'a str, + ) -> Self { + Self { + kind, + adapter_version, + protocol_revision, + browser_revision, + } + } +} + impl BrowserProtocolAdapterDescriptor { /// Validate current browser-protocol metadata and immediately invoke one dispatch callback. /// - /// The runtime protocol family, adapter version, protocol revision, and browser revision must - /// be sampled from the trusted adapter that is about to perform the operation. Validation - /// occurs before `dispatch` is invoked, and the callback receives the resulting non-cloneable - /// [`ValidatedBrowserProtocolUse`] by ownership so this boundary does not turn successful - /// validation into reusable ambient authority. + /// `runtime_metadata` must be sampled from the trusted adapter that is about to perform the + /// operation. Validation occurs before `dispatch` is invoked, and the callback receives the + /// resulting non-cloneable [`ValidatedBrowserProtocolUse`] by ownership so this boundary does + /// not turn successful validation into reusable ambient authority. /// /// A successful callback invocation does not authenticate the adapter process, authorize a /// browser session, browsing context, origin, destination, secret, or approval, or prove a @@ -18,10 +51,7 @@ impl BrowserProtocolAdapterDescriptor { pub fn dispatch_if_runtime_matches( &self, required_originweave_protocol_version: OriginWeaveProtocolVersion, - runtime_kind: BrowserProtocolKind, - runtime_adapter_version: &str, - runtime_protocol_revision: &str, - runtime_browser_revision: &str, + runtime_metadata: BrowserProtocolRuntimeMetadata<'_>, required_capability: BrowserProtocolCapability, dispatch: F, ) -> Result @@ -30,10 +60,10 @@ impl BrowserProtocolAdapterDescriptor { { let validated = self.validate_use( required_originweave_protocol_version, - runtime_kind, - runtime_adapter_version, - runtime_protocol_revision, - runtime_browser_revision, + runtime_metadata.kind, + runtime_metadata.adapter_version, + runtime_metadata.protocol_revision, + runtime_metadata.browser_revision, required_capability, )?; Ok(dispatch(validated)) diff --git a/crates/originweave-core/src/lib.rs b/crates/originweave-core/src/lib.rs index 70cafa890..8e67d18d6 100644 --- a/crates/originweave-core/src/lib.rs +++ b/crates/originweave-core/src/lib.rs @@ -22,6 +22,7 @@ pub use browser_protocol::{ BrowserProtocolVersionRequirementError, MAX_BROWSER_PROTOCOL_METADATA_BYTES, OriginWeaveProtocolVersion, OriginWeaveProtocolVersionParseError, ValidatedBrowserProtocolUse, }; +pub use browser_protocol_dispatch::BrowserProtocolRuntimeMetadata; pub use browser_registry::{ BrowserAuthorityRegistry, BrowserRegistryError, MAX_EXTERNAL_BROWSER_IDENTIFIER_BYTES, }; diff --git a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs index a16334fcf..0ca669d7d 100644 --- a/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs +++ b/crates/originweave-core/tests/browser_protocol_runtime_dispatch.rs @@ -2,7 +2,8 @@ use std::{cell::Cell, error::Error}; use originweave_core::{ BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind, - BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, ValidatedBrowserProtocolUse, + BrowserProtocolRuntimeMetadata, BrowserProtocolUseValidationError, OriginWeaveProtocolVersion, + ValidatedBrowserProtocolUse, }; const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion = @@ -29,6 +30,15 @@ fn descriptor() -> Result> { )?) } +fn runtime_metadata(adapter_version: &str) -> BrowserProtocolRuntimeMetadata<'_> { + BrowserProtocolRuntimeMetadata::new( + BrowserProtocolKind::WebDriverBiDi, + adapter_version, + PROTOCOL_REVISION, + BROWSER_REVISION, + ) +} + fn reset_dispatch_marker() { DISPATCH_CALLED.with(|called| called.set(false)); } @@ -57,10 +67,7 @@ fn exact_runtime_validation_hands_single_use_proof_to_dispatch() -> Result<(), B let dispatch_result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, - BrowserProtocolKind::WebDriverBiDi, - ADAPTER_VERSION, - PROTOCOL_REVISION, - BROWSER_REVISION, + runtime_metadata(ADAPTER_VERSION), BrowserProtocolCapability::Navigation, successful_dispatch as DispatchFn, )?; @@ -83,10 +90,7 @@ fn runtime_mismatch_prevents_dispatch_callback() -> Result<(), Box> { let result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, - BrowserProtocolKind::WebDriverBiDi, - "originweave-bidi-v2", - PROTOCOL_REVISION, - BROWSER_REVISION, + runtime_metadata("originweave-bidi-v2"), BrowserProtocolCapability::Navigation, successful_dispatch as DispatchFn, ); @@ -106,10 +110,7 @@ fn adapter_callback_failure_remains_separate_after_validation() -> Result<(), Bo let dispatch_result = descriptor.dispatch_if_runtime_matches( ORIGINWEAVE_PROTOCOL_VERSION, - BrowserProtocolKind::WebDriverBiDi, - ADAPTER_VERSION, - PROTOCOL_REVISION, - BROWSER_REVISION, + runtime_metadata(ADAPTER_VERSION), BrowserProtocolCapability::Navigation, failing_dispatch as DispatchFn, )?;