From be0c74573b713e3fb55229be8d5f0d95a070588f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:01:51 +0900 Subject: [PATCH 01/16] test(bidi): require screen-area ownership before mutation --- ...webdriver_bidi_screen_settings_contract.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 927c3e06e..36100d1f0 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,15 +13,16 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_explicit_screen_settings_override(self) -> None: - """The qualified BiDi adapter must expose the standard operation as explicit partial intent.""" + def test_adapter_exposes_screen_area_value_without_unowned_mutation_intent(self) -> None: + """Geometry may be typed before Browser Session proves authority to mutate it.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) - self.assertIn("SetScreenArea", text) - self.assertIn("plan_explicit_screen_area_override", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) + self.assertNotIn("SetScreenArea", text) + self.assertNotIn("ResetScreenArea", text) + self.assertNotIn("plan_explicit_screen_area_override", text) + self.assertNotIn("plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -48,7 +49,7 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) planner, "WebDriver BiDi screen settings override also changes screen.availWidth/availHeight; " "the reusable profile-derived plan must model those observables or keep the override " - "behind a separately explicit partial intent", + "behind Browser Session ownership", ) self.assertNotIn( "ResetScreenArea", @@ -57,16 +58,17 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) "not own or install", ) - def test_explicit_cleanup_uses_context_scoped_screen_area_reset(self) -> None: - """The explicit screen-area cleanup must use the command's nullable context-scoped reset.""" + def test_screen_area_mutation_requires_browser_session_ownership(self) -> None: + """A context identifier alone cannot authorize replacing or clearing another owner's override.""" text = SOURCE.read_text(encoding="utf-8") - self.assertIn("ResetScreenArea", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) - self.assertNotIn("ResetMediaFeatures", text) + self.assertNotIn("SetScreenArea", text) + self.assertNotIn("ResetScreenArea", text) + self.assertNotIn("plan_explicit_screen_area_override", text) + self.assertNotIn("plan_explicit_screen_area_cleanup", text) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: - """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" + """Screen-area representation cannot satisfy the complete page-observable Screen contract.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 @@ -79,7 +81,7 @@ def test_screen_surface_remains_fail_closed_until_complete_observables_are_contr ) def test_screen_area_payload_does_not_carry_color_depth(self) -> None: - """The command intent must not imply authority over an unapplied screen observable.""" + """The protocol value must not imply authority over an unapplied screen observable.""" text = SOURCE.read_text(encoding="utf-8") screen_area = text.split("pub struct WebDriverBidiScreenArea", maxsplit=1)[1] screen_area = screen_area.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] From f6ad7387cf9c3d96edc8eb15528807fe62c97b04 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:04:18 +0900 Subject: [PATCH 02/16] fix(bidi): withhold unowned screen-area mutation --- .../src/presentation_capabilities.rs | 120 +++++------------- 1 file changed, 35 insertions(+), 85 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index 6ac5719e1..b44d616e4 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -49,9 +49,10 @@ impl WebDriverBidiBrowsingContext { /// `emulation.setScreenSettingsOverride`. /// /// WebDriver BiDi applies one rectangle to both the web-exposed total screen area and available -/// screen area. Construction therefore remains an explicit partial capability: it projects width and -/// height from validated [`ScreenMetrics`] but does not claim that the presentation profile models the -/// resulting `screen.availWidth` / `screen.availHeight` observables or screen color depth. +/// screen area. This value deliberately represents geometry only: a browsing-context identifier does +/// not prove that OriginWeave owns the existing override and therefore cannot authorize replacing or +/// clearing it. A Browser Session owner must establish an exclusive/disposable context or equivalent +/// ownership witness before a transport adapter may materialize the mutation. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct WebDriverBidiScreenArea { width_px: u32, @@ -61,9 +62,10 @@ pub struct WebDriverBidiScreenArea { impl WebDriverBidiScreenArea { /// Project the protocol-owned rectangle from validated presentation screen metrics. /// - /// The returned value intentionally means that total and available screen areas will be coupled to - /// the same rectangle. It must not be inserted into a profile-derived reusable plan unless the - /// presentation schema has first modelled and authorized those available-area observables. + /// The returned value intentionally means that total and available screen areas would be coupled + /// to the same rectangle if an authorized Browser Session later applies it. Constructing this + /// value grants no mutation or cleanup authority and does not claim that the presentation profile + /// models `screen.availWidth`, `screen.availHeight`, or screen color depth. #[must_use] pub const fn from_screen(screen: &ScreenMetrics) -> Self { Self { @@ -72,13 +74,13 @@ impl WebDriverBidiScreenArea { } } - /// Return the width applied to both total and available web-exposed screen areas. + /// Return the width represented for both total and available web-exposed screen areas. #[must_use] pub const fn width(&self) -> u32 { self.width_px } - /// Return the height applied to both total and available web-exposed screen areas. + /// Return the height represented for both total and available web-exposed screen areas. #[must_use] pub const fn height(&self) -> u32 { self.height_px @@ -90,20 +92,12 @@ impl WebDriverBidiScreenArea { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// screen, viewport, DPR, or time-zone validation. Screen-area commands couple total and available -/// screen geometry, do not control color depth, and therefore do not satisfy the complete -/// `PresentationSurface::Screen` contract. This reusable-boundary enum deliberately exposes no -/// media-feature mutation command because this crate has no ownership or snapshot witness that would -/// make such mutation reversibly safe. +/// viewport, DPR, or time-zone validation. Screen-area mutation is intentionally absent: the standard +/// operation replaces or removes context state, while this adapter has no ownership or snapshot +/// witness proving that such state belongs to OriginWeave. This reusable-boundary enum deliberately +/// exposes no media-feature mutation command for the same non-destructive-cleanup reason. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { - /// Set total and available web-exposed screen width and height together. - SetScreenArea { - /// Exact target browsing context. - context: WebDriverBidiBrowsingContext, - /// Exact coupled standard-BiDi screen-area payload derived from validated screen metrics. - screen_area: WebDriverBidiScreenArea, - }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { /// Exact target browsing context. @@ -120,11 +114,6 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, - /// Remove the coupled total-and-available screen-area override for the exact browsing context. - ResetScreenArea { - /// Exact target browsing context. - context: WebDriverBidiBrowsingContext, - }, /// Restore the implementation-defined viewport and remove the device-pixel-ratio override. ResetViewport { /// Exact target browsing context. @@ -137,46 +126,17 @@ pub enum WebDriverBidiPresentationCommand { }, } -/// Plan one explicit partial screen-area override for a bounded browsing context. -/// -/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is -/// deliberately separate from [`plan_standard_presentation_commands`] because the current -/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`; callers must not -/// mistake this explicit coupled operation for application of the complete profile. -#[must_use] -pub fn plan_explicit_screen_area_override( - context: &WebDriverBidiBrowsingContext, - screen: &ScreenMetrics, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area: WebDriverBidiScreenArea::from_screen(screen), - } -} - -/// Plan cleanup for one explicitly applied coupled screen-area override. -/// -/// The pinned Working Draft defines `screenArea: null` as removal of that exact context-scoped -/// override. Planning the reset does not prove transport execution or post-cleanup page observation. -#[must_use] -pub fn plan_explicit_screen_area_cleanup( - context: &WebDriverBidiBrowsingContext, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::ResetScreenArea { - context: context.clone(), - } -} - /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the -/// pinned Working Draft. The screen-settings override is excluded from this profile-derived plan even -/// though it is reversible because it also changes the unmodelled page-observable available screen -/// area. Reduced motion remains an expressible protocol capability, but this reusable planning boundary -/// neither installs nor exposes a media-mutation command because `features: null` clears the complete -/// media-feature configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` -/// value. The explicit arguments make this a partial-plan API: it cannot be mistaken for application of -/// a complete [`originweave_fingerprint::PresentationProfile`]. +/// pinned Working Draft. Screen-area mutation is excluded even as an explicit context-only command: +/// setting a rectangle can replace another owner's override and `screenArea: null` removes the current +/// override rather than restoring a prior value. Reduced motion remains an expressible protocol +/// capability, but this reusable planning boundary neither installs nor exposes a media-mutation +/// command because `features: null` clears the complete media-feature configuration rather than +/// restoring only OriginWeave's prior `prefers-reduced-motion` value. The explicit arguments make this +/// a partial-plan API: it cannot be mistaken for application of a complete +/// [`originweave_fingerprint::PresentationProfile`]. #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, @@ -201,8 +161,8 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is deliberately separate because this reusable plan does not install the coupled total-and- -/// available screen override. Media cleanup is absent because `features: null` clears the complete +/// cleanup is absent because this boundary cannot prove ownership of the current screen override or +/// restore a predecessor value. Media cleanup is absent because `features: null` clears the complete /// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( @@ -243,10 +203,12 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// The protocol can explicitly couple total and available screen width/height through /// `emulation.setScreenSettingsOverride`, but OriginWeave's `Screen` surface also includes color depth /// and the current profile does not model the available screen rectangle. `Screen` therefore remains -/// intentionally absent. Ordered-language surfaces, hardware concurrency, and the Chromium -/// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol -/// capability even though reusable application leaves media state untouched until a Browser Session -/// owner supplies a restorable lifecycle and corresponding command authority. +/// intentionally absent. This adapter additionally withholds screen-area mutation until Browser +/// Session proves ownership of the affected override lifecycle. Ordered-language surfaces, hardware +/// concurrency, and the Chromium platform/User-Agent Client Hints surface are also absent. Reduced +/// motion is listed as protocol capability even though reusable application leaves media state +/// untouched until a Browser Session owner supplies a restorable lifecycle and corresponding command +/// authority. #[must_use] pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSurface] { &WEBDRIVER_BIDI_PRESENTATION_SURFACES @@ -255,9 +217,10 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area -/// command does not control color depth and additionally couples an available-screen observable absent -/// from the current profile. Callers must not translate that result into ambient-host fallback. +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the standard screen-area +/// value does not control color depth, the profile does not model available-screen geometry, and this +/// adapter has no Browser Session ownership witness for mutating existing screen-settings state. +/// Callers must not translate that result into ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -301,7 +264,7 @@ mod tests { } #[test] - fn explicit_screen_area_command_preserves_the_protocol_coupling_boundary() { + fn screen_area_value_preserves_protocol_coupling_without_mutation_authority() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -313,23 +276,10 @@ mod tests { true, ) .expect("consistent profile"); - let context = - WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); - assert_eq!( - plan_explicit_screen_area_override(&context, profile.screen()), - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area, - } - ); - assert_eq!( - plan_explicit_screen_area_cleanup(&context), - WebDriverBidiPresentationCommand::ResetScreenArea { context } - ); } #[test] From 597108d560ae44770eccab04676dcd10956238a5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:06:59 +0900 Subject: [PATCH 03/16] test(bidi): bind screen-area intent to ownership witness --- ...webdriver_bidi_screen_settings_contract.py | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 36100d1f0..67832d4ef 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,16 +13,17 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_screen_area_value_without_unowned_mutation_intent(self) -> None: - """Geometry may be typed before Browser Session proves authority to mutate it.""" + def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> None: + """The standard operation stays typed but requires Browser Session ownership.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) - self.assertNotIn("SetScreenArea", text) - self.assertNotIn("ResetScreenArea", text) - self.assertNotIn("plan_explicit_screen_area_override", text) - self.assertNotIn("plan_explicit_screen_area_cleanup", text) + self.assertIn("WebDriverBidiScreenAreaOwnership", text) + self.assertIn("SetScreenArea", text) + self.assertIn("ResetScreenArea", text) + self.assertIn("plan_explicit_screen_area_override", text) + self.assertIn("plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -58,17 +59,36 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) "not own or install", ) - def test_screen_area_mutation_requires_browser_session_ownership(self) -> None: + def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(self) -> None: """A context identifier alone cannot authorize replacing or clearing another owner's override.""" text = SOURCE.read_text(encoding="utf-8") - - self.assertNotIn("SetScreenArea", text) - self.assertNotIn("ResetScreenArea", text) - self.assertNotIn("plan_explicit_screen_area_override", text) - self.assertNotIn("plan_explicit_screen_area_cleanup", text) + ownership = text.split( + "pub struct WebDriverBidiScreenAreaOwnership", maxsplit=1 + )[1].split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] + set_variant = text.split("SetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] + reset_variant = text.split("ResetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] + override_planner = text.split( + "pub fn plan_explicit_screen_area_override", maxsplit=1 + )[1].split("pub fn plan_explicit_screen_area_cleanup", maxsplit=1)[0] + cleanup_planner = text.split( + "pub fn plan_explicit_screen_area_cleanup", maxsplit=1 + )[1].split("pub fn plan_standard_presentation_commands", maxsplit=1)[0] + + self.assertIn("context: WebDriverBidiBrowsingContext", ownership) + self.assertNotIn("pub context:", ownership) + self.assertNotIn("pub fn new(", ownership) + self.assertNotIn("pub fn from_", ownership) + self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", set_variant) + self.assertNotIn("context: WebDriverBidiBrowsingContext", set_variant) + self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", reset_variant) + self.assertNotIn("context: WebDriverBidiBrowsingContext", reset_variant) + self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", override_planner) + self.assertNotIn("context: &WebDriverBidiBrowsingContext", override_planner) + self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", cleanup_planner) + self.assertNotIn("context: &WebDriverBidiBrowsingContext", cleanup_planner) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: - """Screen-area representation cannot satisfy the complete page-observable Screen contract.""" + """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 @@ -81,10 +101,10 @@ def test_screen_surface_remains_fail_closed_until_complete_observables_are_contr ) def test_screen_area_payload_does_not_carry_color_depth(self) -> None: - """The protocol value must not imply authority over an unapplied screen observable.""" + """The command intent must not imply authority over an unapplied screen observable.""" text = SOURCE.read_text(encoding="utf-8") screen_area = text.split("pub struct WebDriverBidiScreenArea", maxsplit=1)[1] - screen_area = screen_area.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] + screen_area = screen_area.split("pub struct WebDriverBidiScreenAreaOwnership", maxsplit=1)[0] self.assertIn("width_px: u32", screen_area) self.assertIn("height_px: u32", screen_area) From fa17e07f9c6cfdc3c3ec69105bf447ed49977990 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:07:40 +0900 Subject: [PATCH 04/16] fix(bidi): gate screen-area commands on ownership witness --- .../src/presentation_capabilities.rs | 153 +++++++++++++----- 1 file changed, 117 insertions(+), 36 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index b44d616e4..d58ccf2b0 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -49,10 +49,9 @@ impl WebDriverBidiBrowsingContext { /// `emulation.setScreenSettingsOverride`. /// /// WebDriver BiDi applies one rectangle to both the web-exposed total screen area and available -/// screen area. This value deliberately represents geometry only: a browsing-context identifier does -/// not prove that OriginWeave owns the existing override and therefore cannot authorize replacing or -/// clearing it. A Browser Session owner must establish an exclusive/disposable context or equivalent -/// ownership witness before a transport adapter may materialize the mutation. +/// screen area. Construction therefore remains an explicit partial capability: it projects width and +/// height from validated [`ScreenMetrics`] but does not claim that the presentation profile models the +/// resulting `screen.availWidth` / `screen.availHeight` observables or screen color depth. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct WebDriverBidiScreenArea { width_px: u32, @@ -62,10 +61,9 @@ pub struct WebDriverBidiScreenArea { impl WebDriverBidiScreenArea { /// Project the protocol-owned rectangle from validated presentation screen metrics. /// - /// The returned value intentionally means that total and available screen areas would be coupled - /// to the same rectangle if an authorized Browser Session later applies it. Constructing this - /// value grants no mutation or cleanup authority and does not claim that the presentation profile - /// models `screen.availWidth`, `screen.availHeight`, or screen color depth. + /// The returned value intentionally means that total and available screen areas will be coupled to + /// the same rectangle. It must not be inserted into a profile-derived reusable plan unless the + /// presentation schema has first modelled and authorized those available-area observables. #[must_use] pub const fn from_screen(screen: &ScreenMetrics) -> Self { Self { @@ -74,30 +72,59 @@ impl WebDriverBidiScreenArea { } } - /// Return the width represented for both total and available web-exposed screen areas. + /// Return the width applied to both total and available web-exposed screen areas. #[must_use] pub const fn width(&self) -> u32 { self.width_px } - /// Return the height represented for both total and available web-exposed screen areas. + /// Return the height applied to both total and available web-exposed screen areas. #[must_use] pub const fn height(&self) -> u32 { self.height_px } } +/// Proof that Browser Session owns screen-settings mutation for one browsing context. +/// +/// This type intentionally has no public constructor. A remote-issued context identifier is identity, +/// not authority: WebDriver BiDi replaces the current screen-area override when setting a rectangle and +/// removes it when `screenArea` is null. A Browser Session integration may create this witness only +/// after it has established an exclusive/disposable context or an equivalent lifecycle that proves no +/// unrelated owner state can be overwritten or cleared. Until that integration exists, external +/// callers can inspect neither a mint path nor a context-only escape hatch for screen-area mutation. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WebDriverBidiScreenAreaOwnership { + context: WebDriverBidiBrowsingContext, +} + +impl WebDriverBidiScreenAreaOwnership { + /// Return the exact browsing context covered by this ownership witness. + #[must_use] + pub const fn context(&self) -> &WebDriverBidiBrowsingContext { + &self.context + } +} + /// Typed standard-BiDi presentation command intent for one explicit browsing context. /// /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// viewport, DPR, or time-zone validation. Screen-area mutation is intentionally absent: the standard -/// operation replaces or removes context state, while this adapter has no ownership or snapshot -/// witness proving that such state belongs to OriginWeave. This reusable-boundary enum deliberately -/// exposes no media-feature mutation command for the same non-destructive-cleanup reason. +/// screen, viewport, DPR, or time-zone validation. Screen-area commands require an opaque Browser +/// Session ownership witness because setting or clearing the context override is destructive to any +/// predecessor value. This reusable-boundary enum deliberately exposes no media-feature mutation +/// command because this crate has no ownership or snapshot witness that would make such mutation +/// reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { + /// Set total and available web-exposed screen width and height together. + SetScreenArea { + /// Browser Session proof that this context's screen-settings lifecycle is exclusively owned. + ownership: WebDriverBidiScreenAreaOwnership, + /// Exact coupled standard-BiDi screen-area payload derived from validated screen metrics. + screen_area: WebDriverBidiScreenArea, + }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { /// Exact target browsing context. @@ -114,6 +141,11 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, + /// Remove the coupled total-and-available screen-area override for the owned browsing context. + ResetScreenArea { + /// Browser Session proof that clearing this context cannot remove another owner's override. + ownership: WebDriverBidiScreenAreaOwnership, + }, /// Restore the implementation-defined viewport and remove the device-pixel-ratio override. ResetViewport { /// Exact target browsing context. @@ -126,17 +158,50 @@ pub enum WebDriverBidiPresentationCommand { }, } +/// Plan one explicit partial screen-area override for a Browser Session-owned browsing context. +/// +/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is +/// deliberately separate from [`plan_standard_presentation_commands`] because the current +/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`. Possession of the +/// opaque ownership witness is additionally required because replacing the existing context override +/// is not a reversible context-only operation. +#[must_use] +pub fn plan_explicit_screen_area_override( + ownership: &WebDriverBidiScreenAreaOwnership, + screen: &ScreenMetrics, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area: WebDriverBidiScreenArea::from_screen(screen), + } +} + +/// Plan cleanup for one explicitly applied, Browser Session-owned screen-area override. +/// +/// The pinned Working Draft defines `screenArea: null` as removal of the exact context-scoped override; +/// it does not restore a predecessor value. Requiring the same opaque ownership witness prevents a raw +/// browsing-context identifier from becoming cleanup authority. Planning still proves neither transport +/// execution nor post-cleanup page observation. +#[must_use] +pub fn plan_explicit_screen_area_cleanup( + ownership: &WebDriverBidiScreenAreaOwnership, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::ResetScreenArea { + ownership: ownership.clone(), + } +} + /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the -/// pinned Working Draft. Screen-area mutation is excluded even as an explicit context-only command: -/// setting a rectangle can replace another owner's override and `screenArea: null` removes the current -/// override rather than restoring a prior value. Reduced motion remains an expressible protocol -/// capability, but this reusable planning boundary neither installs nor exposes a media-mutation -/// command because `features: null` clears the complete media-feature configuration rather than -/// restoring only OriginWeave's prior `prefers-reduced-motion` value. The explicit arguments make this -/// a partial-plan API: it cannot be mistaken for application of a complete -/// [`originweave_fingerprint::PresentationProfile`]. +/// pinned Working Draft. The screen-settings override is excluded from this profile-derived plan even +/// though the protocol exposes a nullable reset because it also changes the unmodelled page-observable +/// available screen area and requires Browser Session ownership of the predecessor state. Reduced +/// motion remains an expressible protocol capability, but this reusable planning boundary neither +/// installs nor exposes a media-mutation command because `features: null` clears the complete +/// media-feature configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` +/// value. The explicit arguments make this a partial-plan API: it cannot be mistaken for application of +/// a complete [`originweave_fingerprint::PresentationProfile`]. #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, @@ -161,9 +226,10 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is absent because this boundary cannot prove ownership of the current screen override or -/// restore a predecessor value. Media cleanup is absent because `features: null` clears the complete -/// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. +/// cleanup is deliberately separate and ownership-gated because `screenArea: null` removes the current +/// override rather than restoring any predecessor. Media cleanup is absent because `features: null` +/// clears the complete media-feature override configuration rather than selectively undoing +/// `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( context: &WebDriverBidiBrowsingContext, @@ -203,12 +269,10 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// The protocol can explicitly couple total and available screen width/height through /// `emulation.setScreenSettingsOverride`, but OriginWeave's `Screen` surface also includes color depth /// and the current profile does not model the available screen rectangle. `Screen` therefore remains -/// intentionally absent. This adapter additionally withholds screen-area mutation until Browser -/// Session proves ownership of the affected override lifecycle. Ordered-language surfaces, hardware -/// concurrency, and the Chromium platform/User-Agent Client Hints surface are also absent. Reduced -/// motion is listed as protocol capability even though reusable application leaves media state -/// untouched until a Browser Session owner supplies a restorable lifecycle and corresponding command -/// authority. +/// intentionally absent. Ordered-language surfaces, hardware concurrency, and the Chromium +/// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol +/// capability even though reusable application leaves media state untouched until a Browser Session +/// owner supplies a restorable lifecycle and corresponding command authority. #[must_use] pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSurface] { &WEBDRIVER_BIDI_PRESENTATION_SURFACES @@ -217,10 +281,10 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the standard screen-area -/// value does not control color depth, the profile does not model available-screen geometry, and this -/// adapter has no Browser Session ownership witness for mutating existing screen-settings state. -/// Callers must not translate that result into ambient-host fallback. +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area +/// command does not control color depth, additionally couples an available-screen observable absent +/// from the current profile, and cannot be materialized until Browser Session supplies ownership of the +/// screen-settings lifecycle. Callers must not translate that result into ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -264,7 +328,7 @@ mod tests { } #[test] - fn screen_area_value_preserves_protocol_coupling_without_mutation_authority() { + fn explicit_screen_area_commands_require_the_same_ownership_witness() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -276,10 +340,27 @@ mod tests { true, ) .expect("consistent profile"); + let context = + WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); + let ownership = WebDriverBidiScreenAreaOwnership { + context: context.clone(), + }; let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + assert_eq!(ownership.context(), &context); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); + assert_eq!( + plan_explicit_screen_area_override(&ownership, profile.screen()), + WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area, + } + ); + assert_eq!( + plan_explicit_screen_area_cleanup(&ownership), + WebDriverBidiPresentationCommand::ResetScreenArea { ownership } + ); } #[test] From c85a4bf5effa415295c1024ea26161d17954d6ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:08:06 +0900 Subject: [PATCH 05/16] docs(bidi): single-source publication freshness --- docs/doctoring.md | 64 +++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/docs/doctoring.md b/docs/doctoring.md index 0fb13a2fc..44fb51d13 100644 --- a/docs/doctoring.md +++ b/docs/doctoring.md @@ -51,42 +51,32 @@ that a non-mobile user agent reports an empty model (see ADR 0112). The pinned 3 September 2026 WebDriver BiDi Working Draft exposes locale, media, screen, user-agent, viewport, and time-zone emulation commands under the immutable publication `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. The screen -settings shape contains width and height but not color depth, and locale accepts one -value rather than an ordered language list, so neither proves the corresponding -complete OriginWeave surface. The 9 September 2026 Working Draft retains the relevant -`emulation.setScreenSettingsOverride` shape; that publication update is tracked -separately and does not silently repin runtime compatibility. - -The screen-settings operation has a second page-observable effect that the earlier -planner description omitted: the specification applies the same `screenArea` -rectangle to both the web-exposed total screen area and the web-exposed available -screen area. OriginWeave `ScreenMetrics` currently models width, height, and color -depth but not `screen.availWidth` or `screen.availHeight`. A reusable profile-derived -planner therefore cannot silently schedule this operation merely because it has a -nullable reset. PR #310 keeps the typed `WebDriverBidiScreenArea` capability and its -context-scoped reset, but exposes them as a separately explicit partial intent; the -ordinary reusable plan remains viewport/DPR plus timezone until available-screen -geometry is deliberately represented and digest-bound by the presentation identity. -Complete `PresentationSurface::Screen` admission remains fail-closed because color -depth is still uncontrolled as well. - -The draft does not define a hardware-concurrency override. Chromium's tip-of-tree -DevTools Protocol exposes `Emulation.setHardwareConcurrencyOverride` as Experimental -and warns that tip-of-tree commands can change without notice. OriginWeave therefore -records required presentation surfaces in a protocol-neutral Rust admission contract. -Reduced motion remains an expressible protocol capability, but the reusable-context -plan neither installs it nor emits a media reset because -`emulation.setMediaFeaturesOverride` with `features: null` clears the complete media -configuration rather than selectively reversing only `prefers-reduced-motion`. -No caller-mintable exclusive reset substitutes for Browser Session ownership evidence. -Constructing application or cleanup intents performs no transport I/O and cannot be -treated as acknowledgement, successful cleanup, ownership evidence, or page-observed -presentation evidence. A later pinned Chromium adapter must capability-negotiate every -surface, observe post-conditions after apply and cleanup, and either prove exclusive -disposable context ownership or restore the complete pre-existing configuration before -reusing the browser boundary. The focused screen-area evidence and alternatives are -recorded in `docs/doctoring/webdriver-bidi-screen-area.md` and -`docs/traceability/webdriver-bidi-screen-area-planning.md`. +shape contains width and height but not color depth, and locale accepts one value +rather than an ordered language list, so neither proves the corresponding complete +OriginWeave surface. The draft also does not define a hardware-concurrency +override. Chromium's tip-of-tree DevTools Protocol exposes +`Emulation.setHardwareConcurrencyOverride` as Experimental and warns that +tip-of-tree commands can change without notice. OriginWeave therefore records +required presentation surfaces in a protocol-neutral Rust admission contract; +the adapter records those four complete standard surfaces as protocol +capabilities, while the reusable-context plan emits only two typed command +intents—viewport/DPR and timezone—bound to one bounded opaque browsing context. + +Cleanup authority is asymmetric. Nullable viewport and timezone operations can +restore those adapter-owned overrides on a reusable context, so generic cleanup +plans reset viewport/DPR and timezone. By contrast, +`emulation.setMediaFeaturesOverride` with `features: null` unsets the target's +complete media-feature override configuration rather than selectively reversing +only `prefers-reduced-motion`. The reusable-context plan therefore neither +installs reduced motion nor emits a media reset. No caller-mintable exclusive +reset is exposed as ownership evidence; a Browser Session owner must prove a +disposable context lifecycle or restore the complete prior media configuration. Constructing application or cleanup +intents performs no transport I/O and cannot be treated as acknowledgement, +successful cleanup, ownership evidence, or page-observed presentation evidence. +A later pinned Chromium adapter must capability-negotiate every surface, observe +post-conditions after apply and cleanup, and either prove exclusive disposable +context ownership or restore the complete pre-existing media configuration +before reusing the browser boundary. ### Extension-to-Agent grant origin binding @@ -276,8 +266,6 @@ World Wide Web Consortium. (2013). *PROV-O: The PROV ontology*. https://www.w3.o World Wide Web Consortium. (2025, September 25). *Mitigating browser fingerprinting in Web specifications*. https://www.w3.org/TR/fingerprinting-guidance/ -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ - World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ World Wide Web Consortium. (2026). *WebDriver BiDi* (Editor's Draft). https://w3c.github.io/webdriver-bidi/ From 48373090dd982b1f853731957078d0ef4f744961 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:09:04 +0900 Subject: [PATCH 06/16] docs(bidi): bind screen-area reset to owned lifecycle --- docs/doctoring/webdriver-bidi-screen-area.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md index 5fcf5fa01..a6dcdce63 100644 --- a/docs/doctoring/webdriver-bidi-screen-area.md +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -1,17 +1,17 @@ # WebDriver BiDi screen-area doctoring -The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. The current 9 September 2026 publication retains the same relevant `emulation.setScreenSettingsOverride` shape, but publication freshness does not itself change OriginWeave's runtime pin. +The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. Publication freshness is tracked separately in `docs/traceability/webdriver-bidi-publication-current.md` and does not by itself change OriginWeave's runtime pin. -For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. The W3C operation uses the same non-null rectangle for both the web-exposed total screen area and the web-exposed available screen area; `screenArea: null` removes that context-scoped override. The reset is symmetric, but the mutation is wider than `ScreenMetrics(width, height, color_depth)` because the current presentation identity does not model `screen.availWidth` or `screen.availHeight`. +For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. The W3C operation uses the same non-null rectangle for both the web-exposed total screen area and the web-exposed available screen area. When `screenArea` is `null`, the remote end removes that context from the screen-settings override map; the command does not restore any predecessor override value. -OriginWeave therefore exposes this as an explicit partial `WebDriverBidiScreenArea` intent rather than inserting it into the reusable profile-derived presentation plan. The value object can only project width and height from validated `ScreenMetrics`, and its rustdoc makes the total/available-area coupling explicit. The ordinary reusable planner remains limited to viewport/DPR and time zone until the presentation schema deliberately models and digest-binds the available-screen observable. +That lifecycle matters independently of the profile schema. `ScreenMetrics(width, height, color_depth)` still does not model `screen.availWidth` or `screen.availHeight`, so the reusable profile-derived plan cannot silently apply the operation. A raw `WebDriverBidiBrowsingContext` also cannot authorize the separate explicit operation: replacing or removing the current override could mutate state installed by another owner. -The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an explicit screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. +OriginWeave therefore keeps `WebDriverBidiScreenArea` as the typed width/height representation but gates `SetScreenArea`, `ResetScreenArea`, and both explicit planners on an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. -This evidence changes only typed command planning. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence, including post-reset re-observation before a reusable context can be trusted again. +The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an owned screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. + +This evidence changes typed command authority only. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence, including post-reset observation and actual disposable-context destruction or equivalent restoration proof before a reusable boundary can be trusted again. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ - -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From aee332cc0cd631770d0747d0f0ed6faf6d8d2877 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:09:22 +0900 Subject: [PATCH 07/16] docs(bidi): trace screen-area ownership authority --- .../webdriver-bidi-screen-area-planning.md | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md index f99e056a5..0a10842dd 100644 --- a/docs/traceability/webdriver-bidi-screen-area-planning.md +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -2,52 +2,58 @@ ## Problem -The runtime-qualified WebDriver BiDi adapter already plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. OriginWeave did not expose that standard operation in its typed planning boundary. +The runtime-qualified WebDriver BiDi adapter plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. The screen operation is wider and more destructive than its width/height payload initially suggests. -The operation is not merely a narrower version of `PresentationSurface::Screen`. WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total screen area and the web-exposed available screen area. OriginWeave `ScreenMetrics` currently models width, height, and color depth, but not `screen.availWidth` or `screen.availHeight`. Automatically deriving the command from `ScreenMetrics` inside the reusable profile plan would therefore mutate a page-observable fingerprint surface that the profile neither selected nor digest-bound. Color depth remains independently uncontrolled as well. +WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total screen area and the web-exposed available screen area. OriginWeave `ScreenMetrics` currently models width, height, and color depth, but not `screen.availWidth` or `screen.availHeight`. Automatically deriving the command from `ScreenMetrics` inside the reusable profile plan would therefore mutate a page-observable fingerprint surface that the profile neither selected nor digest-bound. Color depth remains independently uncontrolled. + +A second authority defect remains even when the operation is separated from the profile-derived plan. The standard stores one override per target browsing context. Setting a rectangle replaces that target's current override; `screenArea: null` removes the target from the override map. The standard does not restore a predecessor value. A validated browsing-context identifier therefore identifies where a mutation would occur but does not prove that OriginWeave owns the state being replaced or cleared. ## Constraints - Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. - Preserve the runtime-qualified 3 September 2026 Working Draft pin. Publication freshness is owned separately by `webdriver-bidi-publication-current.md`. - Reuse validated presentation value objects rather than reopen raw width/height validation in the adapter. -- A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with a context-scoped, non-destructive reset. +- Do not treat a browsing-context identifier as mutation authority. +- A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with non-destructive cleanup. +- Screen-area mutation requires an exclusive/disposable Browser Session context or equivalent ownership proof before the command can be materialized. - Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. ## Alternatives -1. **Insert screen settings into the reusable profile-derived plan.** Rejected. Although `screenArea: null` provides a symmetric reset, the apply operation also changes the currently unmodelled available-screen rectangle. Reversibility alone does not authorize an additional page observable. +1. **Insert screen settings into the reusable profile-derived plan.** Rejected. The apply operation changes the currently unmodelled available-screen rectangle, and the nullable reset does not restore a predecessor override. 2. **Mark `PresentationSurface::Screen` supported after planning width/height.** Rejected because color depth remains page-observable and uncontrolled, and available-screen geometry is absent from the profile. 3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would contain color depth, which the protocol operation does not apply, while still failing to name the available-screen side effect. -4. **Expose an explicit coupled screen-area partial intent and keep it out of the reusable profile-derived plan.** Selected. `WebDriverBidiScreenArea` projects validated width/height, documents that the same rectangle becomes both total and available screen area, and has a separate context-scoped reset. This preserves the protocol capability without silently broadening the presentation profile. -5. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence. It requires its own test-first bounded change rather than being hidden inside an adapter slice. +4. **Expose context-only explicit Set/Reset commands.** Rejected after review. A context identifier does not establish ownership; setting can replace another owner's override and resetting can erase it without restoration. +5. **Remove the standard capability entirely.** Rejected. The protocol operation is useful and can be represented safely without making it ambient authority. +6. **Keep the typed screen-area value and gate explicit mutation on an opaque Browser Session ownership witness.** Selected. The adapter retains protocol semantics while making lifecycle authority non-caller-mintable until a Browser Session owner proves an exclusive/disposable context or equivalent safe ownership transition. +7. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. ## Decision -`originweave-bidi` exposes `plan_explicit_screen_area_override` and `plan_explicit_screen_area_cleanup` as a separately explicit partial capability. The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone because those are the currently modelled, reusable-plan observables with symmetric resets. +`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership` rather than a raw `WebDriverBidiBrowsingContext`. -`WebDriverBidiScreenArea` can only be derived from validated `ScreenMetrics`; its documentation records that WebDriver BiDi couples total and available screen areas to the same rectangle. The complete capability map intentionally continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models the available-screen observable and controls color depth as well. +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. Possession of the witness is the authority to plan both the apply and matching cleanup for that owned lifecycle; it is not transport acknowledgement or page-observed evidence. -The planner produces typed intent only. Transport execution, page-observed post-conditions, browser/session cleanup evidence, crash recovery, and the remaining Chromium-only presentation surfaces stay with the existing #292/#299 acceptance path and its canonical runtime owners. +The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone. The complete capability map continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models available-screen geometry, controls color depth, and proves the runtime application/cleanup lifecycle. ## Evidence and acceptance -The review finding on PR #310 exact `e3b2b412d8ad880c87354fb3ffd5f5b4ff6cde0d` identified the unmodelled available-screen side effect. Test-first successor `8f74471e1a5414e8781531f968b46807e2d7e3d8` adds a contract that fails whenever the profile-derived reusable planner schedules `SetScreenArea` without available width/height being represented by `ScreenMetrics`. The minimal source repair separates the explicit screen-area operation from the reusable profile-derived plan. +PR #310 review identified two distinct findings. The first was the unmodelled available-screen side effect, repaired by keeping screen-area mutation out of the profile-derived reusable plan. The later exact-head review identified the ownership gap: a context-only `ResetScreenArea` could remove another owner's active override because `screenArea: null` deletes the target's override-map entry rather than restoring a prior value. -Acceptance requires: +The successor contract requires: -- a typed screen-area intent derived from validated screen metrics; -- explicit documentation that one WebDriver BiDi rectangle controls both total and available screen areas; -- a separately explicit context-scoped screen-area reset; +- `WebDriverBidiScreenArea` to remain the typed width/height representation derived from validated screen metrics; +- an opaque `WebDriverBidiScreenAreaOwnership` carrying the exact context with no public mint constructor in the adapter; +- `SetScreenArea`, `ResetScreenArea`, and both explicit planners to require that ownership witness rather than a raw context identifier; - no screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled; - no media-feature reset; -- no color-depth field in the screen-area command value object; and +- no color-depth field in the screen-area value object; and - continued fail-closed complete Screen admission. -Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence and must not be transferred from predecessor heads. +The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That was corrected before acceptance: deleting a useful standard capability is not necessary when its mutation authority can instead be represented explicitly and made non-caller-mintable. + +Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence. A command intent or acknowledgement is never substituted for apply → page-observed post-condition → interaction/outcome → owned cleanup/destruction → post-cleanup observation. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ - -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From 47ab396fd8234e95f53c8a429be30d29b91f5041 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:10:12 +0900 Subject: [PATCH 08/16] docs(adr): govern BiDi screen-area ownership witness --- ...13-webdriver-bidi-screen-area-ownership.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/adr/0113-webdriver-bidi-screen-area-ownership.md diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md new file mode 100644 index 000000000..d8c797a1e --- /dev/null +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -0,0 +1,65 @@ +# ADR 0113: WebDriver BiDi screen-area ownership witness + +- Status: Proposed +- Date: 2026-09-10 +- Supersedes: none +- Superseded by: none +- Refines: ADR 0107 + +## Problem + +ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 then exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. + +The remaining authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. + +## Constraints + +- Keep browser-domain and Browser Session lifecycle authority in OriginWeave. +- Keep WebDriver BiDi as an adapter; protocol addressability is not product authorization. +- Preserve the runtime-qualified 3 September 2026 Working Draft pin until a separate compatibility change proves a newer revision. +- Preserve the typed `WebDriverBidiScreenArea` width/height representation and the protocol's total/available-area coupling. +- Do not invent a snapshot/restore facility that WebDriver BiDi does not provide. +- Do not let a command acknowledgement substitute for page-observed application or cleanup evidence. +- Keep the reusable profile-derived planner free of screen-area mutation while available-screen geometry remains unmodelled and color depth remains uncontrolled. + +## Alternatives + +1. **Keep context-only Set/Reset planners.** Rejected. Any caller able to supply a valid remote context identifier could replace or delete screen-settings state without proving ownership. +2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. +3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. +4. **Treat a successful Set command as ownership proof.** Rejected. It can already have overwritten another owner's state; acknowledgement is too late to establish authorization. +5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. + +## Decision + +`originweave-bidi` retains `WebDriverBidiScreenArea` and the explicit `SetScreenArea` / `ResetScreenArea` command intents, but both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its public context accessor permits a transport integration that already possesses the witness to address the command without reopening validation. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. + +This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. + +## Security and governance effects + +A remote-issued context identifier is treated as untrusted addressing metadata rather than mutation authority. The ownership witness prevents adapters, MCP callers, LLM output, page content, or other context-aware code from acquiring screen-settings mutation merely by naming a valid browsing context. + +The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If the Browser Session owner cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, screen-area mutation remains unavailable and the complete presentation profile continues to fail closed. + +## Acceptance evidence + +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the tests now require an opaque non-caller-mintable ownership type, require both Set and Reset variants to carry it, require both explicit planners to accept it rather than a raw context, and continue to forbid screen-area commands in the reusable profile-derived plan. + +Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. + +## Risks and follow-up + +The opaque witness deliberately makes screen-area application unusable until Browser Session integration exists. That is preferred to exposing destructive context-only cleanup. The next browser-runtime slice must define where the witness is minted, how exclusivity/disposability is proven, how it is invalidated on context destruction/navigation boundaries where applicable, and how runtime evidence binds the witness to the exact command and cleanup lifecycle. + +If a future WebDriver BiDi revision adds authoritative predecessor-state restoration, the ownership model may be revisited through a separate versioned compatibility decision; publication alone is not sufficient. + +## References + +World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ + +## Related documents + +See ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. From 7bb310507d6f47799489264a17d82280329e2343 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:15:55 +0900 Subject: [PATCH 09/16] docs(adr): index screen-area ownership decision --- docs/adr/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index a9fffa042..25aa31c0c 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -65,10 +65,11 @@ ADR 0013, ADR 0014, ADR 0110, ADR 0111, and ADR 0112 exist only on this document | ADR | Decision | Status | Governs | |---|---|---|---| | [0016](0016-bap-task-lifecycle-authority.md) | BAP task lifecycle and state authority | Proposed | BAP task states, transitions, recovery validation, transition sequencing, and authority separation | +| [0113](0113-webdriver-bidi-screen-area-ownership.md) | WebDriver BiDi screen-area ownership witness | Proposed | Browser Session-owned screen-settings mutation, destructive reset boundary, and fail-closed adapter authority | -ADR 0016 belongs to the active BAP lifecycle feature branch. Indexing it makes the branch documentation graph complete while preserving its Proposed lifecycle and active-PR, non-protected-main maturity. +ADR 0016 belongs to the active BAP lifecycle feature branch. ADR 0113 belongs to the active WebDriver BiDi screen-area ownership successor. Indexing them makes the branch documentation graph complete while preserving Proposed lifecycle and active-PR, non-protected-main maturity. -After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 from Proposed or assert implementation maturity. +After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 or ADR 0113 from Proposed or assert implementation maturity. Other active feature PRs may contain additional Proposed ADRs. Those files are not part of this canonical documentation line until integrated or deliberately reconciled here. Historical PR checks, stale branch state, or chat decisions never transfer ADR acceptance across a changed head. From 8eb3340fde264d34e1cc0f4152dd909a6f634cec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:17:14 +0900 Subject: [PATCH 10/16] docs(adr): discover screen-area ownership decision --- docs/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 622fc7e99..fd2c19ec9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -93,9 +93,10 @@ The second group exists only on this documentation branch until the branch integ ### Proposed decisions introduced by active feature work - [ADR 0016: BAP task lifecycle and state authority](adr/0016-bap-task-lifecycle-authority.md) +- [ADR 0113: WebDriver BiDi screen-area ownership witness](adr/0113-webdriver-bidi-screen-area-ownership.md) -ADR 0016 is owned by this active BAP lifecycle feature branch and remains Proposed. Its presence here makes the branch documentation graph complete without presenting the decision or implementation as protected-main truth before integration. +ADR 0016 is owned by the active BAP lifecycle feature branch. ADR 0113 is owned by the active WebDriver BiDi screen-area ownership successor. Their presence here makes the branch documentation graph complete without presenting either decision or implementation as protected-main truth before integration. -After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 from Proposed or assert implementation maturity. +After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 or ADR 0113 from Proposed or assert implementation maturity. See the [ADR index](adr/README.md) for status rules, required decision structure, supersession rules, and active feature ADRs. The index and each ADR's own status metadata must agree; a PR body, chat transcript, automation prompt, or stale issue reference cannot change ADR status. From f1380ab8e091964ccbdd576d933cf19d696c3791 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:20:11 +0900 Subject: [PATCH 11/16] docs(adr): align screen ownership decision structure --- ...13-webdriver-bidi-screen-area-ownership.md | 90 +++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md index d8c797a1e..96c2a4397 100644 --- a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -1,33 +1,41 @@ # ADR 0113: WebDriver BiDi screen-area ownership witness -- Status: Proposed -- Date: 2026-09-10 -- Supersedes: none -- Superseded by: none -- Refines: ADR 0107 +- **Status:** Proposed +- **Date:** 2026-09-10 +- **Supersedes:** none +- **Superseded by:** none +- **Refines:** ADR 0107 -## Problem +## Context -ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 then exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. +ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. -The remaining authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. +A second authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. -## Constraints +## Decision drivers -- Keep browser-domain and Browser Session lifecycle authority in OriginWeave. -- Keep WebDriver BiDi as an adapter; protocol addressability is not product authorization. -- Preserve the runtime-qualified 3 September 2026 Working Draft pin until a separate compatibility change proves a newer revision. -- Preserve the typed `WebDriverBidiScreenArea` width/height representation and the protocol's total/available-area coupling. -- Do not invent a snapshot/restore facility that WebDriver BiDi does not provide. -- Do not let a command acknowledgement substitute for page-observed application or cleanup evidence. -- Keep the reusable profile-derived planner free of screen-area mutation while available-screen geometry remains unmodelled and color depth remains uncontrolled. +- Preserve the useful typed WebDriver BiDi screen-area capability without granting ambient mutation authority. +- Prevent a raw browsing-context identifier from authorizing replacement or removal of another owner's override. +- Keep cleanup evidence causal: ownership must exist before the destructive mutation, not be inferred from a later command acknowledgement. +- Keep the reusable profile-derived planner limited to observables represented by the profile and paired with safe cleanup semantics. +- Keep complete Screen admission fail-closed while available-screen geometry and color depth remain uncontrolled. -## Alternatives +## Assumptions and authority boundaries + +- Browser-domain and Browser Session lifecycle authority remain in OriginWeave. +- WebDriver BiDi remains an adapter; protocol addressability is not product authorization. +- The runtime-qualified 3 September 2026 Working Draft pin remains unchanged until a separate compatibility change proves a newer revision. +- `WebDriverBidiScreenArea` remains the typed width/height representation of the protocol's coupled total/available-area rectangle. +- This slice has no authoritative predecessor-state snapshot and does not invent one. +- A command acknowledgement is not page-observed application, ownership evidence, cleanup evidence, or restoration evidence. +- Screen-area mutation may become executable only after Browser Session proves an exclusive/disposable browsing context or an equivalent restoration-safe lifecycle. + +## Options considered 1. **Keep context-only Set/Reset planners.** Rejected. Any caller able to supply a valid remote context identifier could replace or delete screen-settings state without proving ownership. 2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. 3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. -4. **Treat a successful Set command as ownership proof.** Rejected. It can already have overwritten another owner's state; acknowledgement is too late to establish authorization. +4. **Treat a successful Set command as ownership proof.** Rejected. The Set can already have overwritten another owner's state; acknowledgement is too late to establish authorization. 5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. ## Decision @@ -38,28 +46,54 @@ The remaining authority problem is independent of that schema gap. WebDriver BiD This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. -## Security and governance effects +## Consequences + +The adapter preserves the standard screen-area value and explicit command vocabulary while making destructive mutation unavailable to ordinary context-aware callers. A later Browser Session integration has a narrow place to attach lifecycle proof instead of widening the browsing-context value object into authorization. + +The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code must remain fail-closed until the lifecycle owner supplies a reviewed witness producer. + +## Failure and degraded behavior + +If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and screen-area Set/Reset cannot be planned by external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, or best-effort cleanup. + +The reusable profile planner continues to omit screen-area mutation. Complete presentation-profile admission continues to return `MissingSurface(Screen)` because available-screen geometry is unmodelled and color depth is uncontrolled. + +## Security / privacy / governance impact A remote-issued context identifier is treated as untrusted addressing metadata rather than mutation authority. The ownership witness prevents adapters, MCP callers, LLM output, page content, or other context-aware code from acquiring screen-settings mutation merely by naming a valid browsing context. -The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If the Browser Session owner cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, screen-area mutation remains unavailable and the complete presentation profile continues to fail closed. +The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If lifecycle ownership cannot be proven, screen-area mutation remains unavailable. -## Acceptance evidence +No identity, egress, secret, policy, approval, or Context Fabric authority moves into the WebDriver BiDi adapter. The decision remains Proposed until policy-compliant protected-main review changes its lifecycle. -The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the tests now require an opaque non-caller-mintable ownership type, require both Set and Reset variants to carry it, require both explicit planners to accept it rather than a raw context, and continue to forbid screen-area commands in the reusable profile-derived plan. +## Tests and acceptance evidence + +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the repository contract now requires an opaque non-caller-mintable ownership type, requires both Set and Reset variants to carry it, requires both explicit planners to accept it rather than a raw context, and continues to forbid screen-area commands in the reusable profile-derived plan. Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. -## Risks and follow-up +## Migration and rollback + +This active branch changes only the typed planner contract. Existing callers that used context-only screen-area planners must not be mechanically migrated by manufacturing a witness; they must move behind the future Browser Session lifecycle owner or remain unable to invoke the operation. + +Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore the context-only public Set/Reset authority without a separate reviewed decision, because that would reintroduce the destructive-cleanup defect. + +## Open follow-ups -The opaque witness deliberately makes screen-area application unusable until Browser Session integration exists. That is preferred to exposing destructive context-only cleanup. The next browser-runtime slice must define where the witness is minted, how exclusivity/disposability is proven, how it is invalidated on context destruction/navigation boundaries where applicable, and how runtime evidence binds the witness to the exact command and cleanup lifecycle. +- Define the Browser Session aggregate transition that mints the witness only after exclusive/disposable-context establishment or equivalent ownership proof. +- Bind witness invalidation to context/session destruction and any lifecycle boundary that makes the proof stale. +- Bind runtime evidence to the exact ownership witness, Set command, page-observed post-condition, cleanup or context destruction, and post-cleanup observation. +- Decide in a separate schema change whether `PresentationProfile` should model available-screen geometry; do not infer it from total screen size. +- Continue #299/#292 real-Chromium acceptance independently of this repository-only authority contract. -If a future WebDriver BiDi revision adds authoritative predecessor-state restoration, the ownership model may be revisited through a separate versioned compatibility decision; publication alone is not sufficient. +## Supersession / reversal conditions + +This ADR may be superseded if a later reviewed Browser Session design provides an equivalent non-forgeable capability with stronger lifetime semantics, or if a future WebDriver BiDi revision adds authoritative predecessor-state restoration that is separately compatibility-qualified. Publication of a newer draft alone is not sufficient. + +It is reversed only if OriginWeave removes the screen-area capability entirely or adopts another reviewed browser protocol boundary that provides equivalent ownership and cleanup guarantees. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ -## Related documents - -See ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. +Related repository evidence: ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. From e5295a0b72c0f2bb5693305a3ffa145a7fa88b30 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:01:35 +0900 Subject: [PATCH 12/16] test(bidi): reject dead screen-area planners before ownership mint --- ...webdriver_bidi_screen_settings_contract.py | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 67832d4ef..00300e2d9 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,8 +13,8 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> None: - """The standard operation stays typed but requires Browser Session ownership.""" + def test_adapter_keeps_screen_area_typed_without_a_dead_external_planner(self) -> None: + """Dormant screen mutation stays typed but has no callable path before ownership can be minted.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) @@ -22,8 +22,8 @@ def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> self.assertIn("WebDriverBidiScreenAreaOwnership", text) self.assertIn("SetScreenArea", text) self.assertIn("ResetScreenArea", text) - self.assertIn("plan_explicit_screen_area_override", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) + self.assertNotIn("pub fn plan_explicit_screen_area_override", text) + self.assertNotIn("pub fn plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -67,12 +67,6 @@ def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(se )[1].split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] set_variant = text.split("SetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] reset_variant = text.split("ResetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] - override_planner = text.split( - "pub fn plan_explicit_screen_area_override", maxsplit=1 - )[1].split("pub fn plan_explicit_screen_area_cleanup", maxsplit=1)[0] - cleanup_planner = text.split( - "pub fn plan_explicit_screen_area_cleanup", maxsplit=1 - )[1].split("pub fn plan_standard_presentation_commands", maxsplit=1)[0] self.assertIn("context: WebDriverBidiBrowsingContext", ownership) self.assertNotIn("pub context:", ownership) @@ -82,10 +76,8 @@ def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(se self.assertNotIn("context: WebDriverBidiBrowsingContext", set_variant) self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", reset_variant) self.assertNotIn("context: WebDriverBidiBrowsingContext", reset_variant) - self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", override_planner) - self.assertNotIn("context: &WebDriverBidiBrowsingContext", override_planner) - self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", cleanup_planner) - self.assertNotIn("context: &WebDriverBidiBrowsingContext", cleanup_planner) + self.assertNotIn("pub fn plan_explicit_screen_area_override", text) + self.assertNotIn("pub fn plan_explicit_screen_area_cleanup", text) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" From 2fc2f64a102a5bf6f87b9d20e709efcab2905c1d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:02:37 +0900 Subject: [PATCH 13/16] fix(bidi): remove unreachable screen-area planner API --- .../src/presentation_capabilities.rs | 67 ++++++------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index d58ccf2b0..b47939e8a 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -92,7 +92,7 @@ impl WebDriverBidiScreenArea { /// removes it when `screenArea` is null. A Browser Session integration may create this witness only /// after it has established an exclusive/disposable context or an equivalent lifecycle that proves no /// unrelated owner state can be overwritten or cleared. Until that integration exists, external -/// callers can inspect neither a mint path nor a context-only escape hatch for screen-area mutation. +/// callers have neither a mint path nor a callable screen-area planner. #[derive(Debug, Clone, PartialEq, Eq)] pub struct WebDriverBidiScreenAreaOwnership { context: WebDriverBidiBrowsingContext, @@ -111,11 +111,11 @@ impl WebDriverBidiScreenAreaOwnership { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// screen, viewport, DPR, or time-zone validation. Screen-area commands require an opaque Browser -/// Session ownership witness because setting or clearing the context override is destructive to any -/// predecessor value. This reusable-boundary enum deliberately exposes no media-feature mutation -/// command because this crate has no ownership or snapshot witness that would make such mutation -/// reversibly safe. +/// screen, viewport, DPR, or time-zone validation. Screen-area command vocabulary retains the opaque +/// Browser Session ownership witness because setting or clearing the context override is destructive to +/// any predecessor value. No public screen-area planner is exposed until Browser Session can mint that +/// witness. This reusable-boundary enum deliberately exposes no media-feature mutation command because +/// this crate has no ownership or snapshot witness that would make such mutation reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { /// Set total and available web-exposed screen width and height together. @@ -158,39 +158,6 @@ pub enum WebDriverBidiPresentationCommand { }, } -/// Plan one explicit partial screen-area override for a Browser Session-owned browsing context. -/// -/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is -/// deliberately separate from [`plan_standard_presentation_commands`] because the current -/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`. Possession of the -/// opaque ownership witness is additionally required because replacing the existing context override -/// is not a reversible context-only operation. -#[must_use] -pub fn plan_explicit_screen_area_override( - ownership: &WebDriverBidiScreenAreaOwnership, - screen: &ScreenMetrics, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::SetScreenArea { - ownership: ownership.clone(), - screen_area: WebDriverBidiScreenArea::from_screen(screen), - } -} - -/// Plan cleanup for one explicitly applied, Browser Session-owned screen-area override. -/// -/// The pinned Working Draft defines `screenArea: null` as removal of the exact context-scoped override; -/// it does not restore a predecessor value. Requiring the same opaque ownership witness prevents a raw -/// browsing-context identifier from becoming cleanup authority. Planning still proves neither transport -/// execution nor post-cleanup page observation. -#[must_use] -pub fn plan_explicit_screen_area_cleanup( - ownership: &WebDriverBidiScreenAreaOwnership, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::ResetScreenArea { - ownership: ownership.clone(), - } -} - /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the @@ -226,9 +193,10 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is deliberately separate and ownership-gated because `screenArea: null` removes the current -/// override rather than restoring any predecessor. Media cleanup is absent because `features: null` -/// clears the complete media-feature override configuration rather than selectively undoing +/// command intent remains ownership-gated, but no callable screen-area cleanup planner exists until +/// Browser Session can mint the ownership witness; `screenArea: null` removes the current override +/// rather than restoring any predecessor. Media cleanup is absent because `features: null` clears the +/// complete media-feature override configuration rather than selectively undoing /// `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( @@ -281,7 +249,7 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the dormant screen-area /// command does not control color depth, additionally couples an available-screen observable absent /// from the current profile, and cannot be materialized until Browser Session supplies ownership of the /// screen-settings lifecycle. Callers must not translate that result into ambient-host fallback. @@ -328,7 +296,7 @@ mod tests { } #[test] - fn explicit_screen_area_commands_require_the_same_ownership_witness() { + fn screen_area_command_shape_requires_the_same_ownership_witness() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -346,19 +314,26 @@ mod tests { context: context.clone(), }; let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + let set_command = WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area, + }; + let reset_command = WebDriverBidiPresentationCommand::ResetScreenArea { + ownership: ownership.clone(), + }; assert_eq!(ownership.context(), &context); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); assert_eq!( - plan_explicit_screen_area_override(&ownership, profile.screen()), + set_command, WebDriverBidiPresentationCommand::SetScreenArea { ownership: ownership.clone(), screen_area, } ); assert_eq!( - plan_explicit_screen_area_cleanup(&ownership), + reset_command, WebDriverBidiPresentationCommand::ResetScreenArea { ownership } ); } From bc3865df57ffdd6300184bbe4a8571bf6deab10d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:11 +0900 Subject: [PATCH 14/16] docs(adr): remove dead planner from ownership decision --- ...13-webdriver-bidi-screen-area-ownership.md | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md index 96c2a4397..be8eb089c 100644 --- a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -12,11 +12,14 @@ ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned clea A second authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. +The first ownership-witness implementation retained public explicit planner functions while intentionally exposing no Browser Session witness-mint path. Exact-head CI `34419810636` made that contradiction executable: Python repository contracts, formatting, and locked workspace tests passed, but strict Clippy rejected both planners as dead production code. Exact production coverage passed separately. A callable planner API with no legal production caller is not a deferred capability; it is unreachable surface area that obscures the lifecycle boundary. + ## Decision drivers -- Preserve the useful typed WebDriver BiDi screen-area capability without granting ambient mutation authority. +- Preserve the useful typed WebDriver BiDi screen-area vocabulary without granting ambient mutation authority. - Prevent a raw browsing-context identifier from authorizing replacement or removal of another owner's override. - Keep cleanup evidence causal: ownership must exist before the destructive mutation, not be inferred from a later command acknowledgement. +- Do not suppress `dead_code` or retain unreachable public helpers merely to advertise a future capability. - Keep the reusable profile-derived planner limited to observables represented by the profile and paired with safe cleanup semantics. - Keep complete Screen admission fail-closed while available-screen geometry and color depth remain uncontrolled. @@ -36,25 +39,28 @@ A second authority problem is independent of that schema gap. WebDriver BiDi sto 2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. 3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. 4. **Treat a successful Set command as ownership proof.** Rejected. The Set can already have overwritten another owner's state; acknowledgement is too late to establish authorization. -5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. +5. **Keep public explicit planners that accept an opaque witness even though no production mint path exists.** Rejected by executable evidence. Exact-head strict Clippy identified both helpers as dead code; suppressing the warning would preserve an API that no legal caller can reach. +6. **Retain the typed command/witness vocabulary but expose no screen-area planner until Browser Session can mint the witness.** Selected. The protocol semantics remain represented, while executable authority appears only when the lifecycle owner supplies a reviewed mint transition and can consume the witness without reopening raw-context authority. ## Decision -`originweave-bidi` retains `WebDriverBidiScreenArea` and the explicit `SetScreenArea` / `ResetScreenArea` command intents, but both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership`. +`originweave-bidi` retains `WebDriverBidiScreenArea`, `WebDriverBidiScreenAreaOwnership`, and the typed `SetScreenArea` / `ResetScreenArea` command variants. Both variants carry the ownership witness rather than a raw `WebDriverBidiBrowsingContext`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its context accessor preserves the target bound to the proof. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. -`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its public context accessor permits a transport integration that already possesses the witness to address the command without reopening validation. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. +Until that mint path exists, the adapter exposes no public explicit screen-area planner. This is deliberate fail-closed capability representation, not an incomplete helper API. When Browser Session adds the ownership transition, the planner/transport path must be introduced in the same reviewed slice so strict Clippy, repository contracts, runtime evidence, and lifecycle invalidation prove that the capability is actually reachable through the canonical owner. -This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. +The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. ## Consequences -The adapter preserves the standard screen-area value and explicit command vocabulary while making destructive mutation unavailable to ordinary context-aware callers. A later Browser Session integration has a narrow place to attach lifecycle proof instead of widening the browsing-context value object into authorization. +The adapter preserves the protocol vocabulary needed for a future owned integration while ordinary context-aware callers cannot plan destructive screen-area mutation. The Browser Session owner now has a narrow future integration point instead of a context-only authorization escape hatch or dead public planner. -The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code must remain fail-closed until the lifecycle owner supplies a reviewed witness producer. +The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code remains fail-closed until the lifecycle owner supplies a reviewed witness producer and a live consumer path. ## Failure and degraded behavior -If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and screen-area Set/Reset cannot be planned by external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, or best-effort cleanup. +If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and no screen-area Set/Reset plan is exposed to external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, best-effort cleanup, or a `dead_code` suppression. The reusable profile planner continues to omit screen-area mutation. Complete presentation-profile admission continues to return `MissingSurface(Screen)` because available-screen geometry is unmodelled and color depth is uncontrolled. @@ -68,19 +74,20 @@ No identity, egress, secret, policy, approval, or Context Fabric authority moves ## Tests and acceptance evidence -The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the repository contract now requires an opaque non-caller-mintable ownership type, requires both Set and Reset variants to carry it, requires both explicit planners to accept it rather than a raw context, and continues to forbid screen-area commands in the reusable profile-derived plan. +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected: the useful protocol vocabulary remains, but the repository contract requires an opaque non-caller-mintable ownership type and requires both Set and Reset variants to carry it. After executable CI exposed the dead-helper contradiction, the contract was tightened to require that no public explicit screen-area planner exists before a Browser Session mint path does. -Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. +Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. The failing `34419810636` run is RED evidence, not acceptance. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. ## Migration and rollback -This active branch changes only the typed planner contract. Existing callers that used context-only screen-area planners must not be mechanically migrated by manufacturing a witness; they must move behind the future Browser Session lifecycle owner or remain unable to invoke the operation. +This active branch changes only the typed authority boundary. Existing callers must not be mechanically migrated by manufacturing a witness. There is intentionally no explicit public planner to call until the future Browser Session lifecycle owner creates the witness and the consuming path together. -Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore the context-only public Set/Reset authority without a separate reviewed decision, because that would reintroduce the destructive-cleanup defect. +Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore context-only public Set/Reset authority or dead planner helpers without a separate reviewed decision, because either would reintroduce the authority or reachability defect. ## Open follow-ups - Define the Browser Session aggregate transition that mints the witness only after exclusive/disposable-context establishment or equivalent ownership proof. +- Add the screen-area planner/transport consumer only in the same slice that makes the ownership witness legitimately mintable and reachable. - Bind witness invalidation to context/session destruction and any lifecycle boundary that makes the proof stale. - Bind runtime evidence to the exact ownership witness, Set command, page-observed post-condition, cleanup or context destruction, and post-cleanup observation. - Decide in a separate schema change whether `PresentationProfile` should model available-screen geometry; do not infer it from total screen size. From 35b95d929c35182913749f8348f56bd2c8ae17f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:22 +0900 Subject: [PATCH 15/16] docs(bidi): record fail-closed planner reachability --- docs/doctoring/webdriver-bidi-screen-area.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md index a6dcdce63..27b0d1ed1 100644 --- a/docs/doctoring/webdriver-bidi-screen-area.md +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -6,7 +6,9 @@ For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `s That lifecycle matters independently of the profile schema. `ScreenMetrics(width, height, color_depth)` still does not model `screen.availWidth` or `screen.availHeight`, so the reusable profile-derived plan cannot silently apply the operation. A raw `WebDriverBidiBrowsingContext` also cannot authorize the separate explicit operation: replacing or removing the current override could mutate state installed by another owner. -OriginWeave therefore keeps `WebDriverBidiScreenArea` as the typed width/height representation but gates `SetScreenArea`, `ResetScreenArea`, and both explicit planners on an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. +OriginWeave therefore keeps `WebDriverBidiScreenArea` and the `SetScreenArea` / `ResetScreenArea` command vocabulary behind an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. + +The first witness implementation also retained two public explicit screen-area planner helpers even though no legal production path could mint the witness. Exact-head CI `34419810636` rejected both helpers under strict Clippy as dead code while repository contracts, formatting, workspace tests, and exact production coverage otherwise passed. OriginWeave does not suppress that finding. Until Browser Session introduces the reviewed witness-mint transition and a real consuming path, the adapter exposes no public explicit screen-area planner; the typed command vocabulary remains dormant and fail-closed. The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an owned screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. From 43377c2de00865d0e92126c455ca6390297c9cf7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:44 +0900 Subject: [PATCH 16/16] docs(trace): bind screen planner repair to executable Clippy RED --- .../webdriver-bidi-screen-area-planning.md | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md index 0a10842dd..1ccbe8ea4 100644 --- a/docs/traceability/webdriver-bidi-screen-area-planning.md +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -8,6 +8,8 @@ WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total A second authority defect remains even when the operation is separated from the profile-derived plan. The standard stores one override per target browsing context. Setting a rectangle replaces that target's current override; `screenArea: null` removes the target from the override map. The standard does not restore a predecessor value. A validated browsing-context identifier therefore identifies where a mutation would occur but does not prove that OriginWeave owns the state being replaced or cleared. +A third reachability defect became executable after the ownership witness was introduced. The adapter intentionally had no production mint path for `WebDriverBidiScreenAreaOwnership` but still retained public explicit screen-area planner helpers. Exact-head CI `34419810636` ran on a GitHub-hosted Ubuntu 24.04 runner: Python repository contracts, formatting, and locked workspace tests passed; exact production coverage passed; strict Clippy failed because both explicit planner functions were dead production code. Keeping those helpers with a lint waiver would advertise executable authority that the canonical Browser Session owner cannot yet provide. + ## Constraints - Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. @@ -16,6 +18,7 @@ A second authority defect remains even when the operation is separated from the - Do not treat a browsing-context identifier as mutation authority. - A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with non-destructive cleanup. - Screen-area mutation requires an exclusive/disposable Browser Session context or equivalent ownership proof before the command can be materialized. +- Do not retain dead public planner helpers or suppress strict Clippy while the ownership mint path is absent. - Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. ## Alternatives @@ -25,14 +28,17 @@ A second authority defect remains even when the operation is separated from the 3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would contain color depth, which the protocol operation does not apply, while still failing to name the available-screen side effect. 4. **Expose context-only explicit Set/Reset commands.** Rejected after review. A context identifier does not establish ownership; setting can replace another owner's override and resetting can erase it without restoration. 5. **Remove the standard capability entirely.** Rejected. The protocol operation is useful and can be represented safely without making it ambient authority. -6. **Keep the typed screen-area value and gate explicit mutation on an opaque Browser Session ownership witness.** Selected. The adapter retains protocol semantics while making lifecycle authority non-caller-mintable until a Browser Session owner proves an exclusive/disposable context or equivalent safe ownership transition. -7. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. +6. **Keep public explicit planners that accept an opaque witness before any production witness-mint path exists.** Rejected by exact-head Clippy RED. No legal production caller can reach them, so they are dead API rather than useful capability. +7. **Retain the typed screen-area value, ownership witness, and Set/Reset command vocabulary, but expose no screen-area planner until Browser Session supplies the mint transition and consumer path.** Selected. Protocol semantics remain explicit while executable authority stays with the lifecycle owner. +8. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. ## Decision -`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership` rather than a raw `WebDriverBidiBrowsingContext`. +`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection, retains opaque `WebDriverBidiScreenAreaOwnership`, and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants carry the ownership witness rather than a raw `WebDriverBidiBrowsingContext`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. -`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. Possession of the witness is the authority to plan both the apply and matching cleanup for that owned lifecycle; it is not transport acknowledgement or page-observed evidence. +There is no public explicit screen-area planner while that mint path is absent. The planner/transport consumer must be introduced together with the reviewed Browser Session ownership transition so strict Clippy and runtime evidence prove a real canonical call path. No `allow(dead_code)`/`expect(dead_code)` exception is used. The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone. The complete capability map continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models available-screen geometry, controls color depth, and proves the runtime application/cleanup lifecycle. @@ -40,17 +46,20 @@ The ordinary `plan_standard_presentation_commands` and `plan_standard_presentati PR #310 review identified two distinct findings. The first was the unmodelled available-screen side effect, repaired by keeping screen-area mutation out of the profile-derived reusable plan. The later exact-head review identified the ownership gap: a context-only `ResetScreenArea` could remove another owner's active override because `screenArea: null` deletes the target's override-map entry rather than restoring a prior value. -The successor contract requires: +The first #311 ownership-witness implementation then exposed a third, executable finding. Run `34419810636` on exact `f1380ab8e091964ccbdd576d933cf19d696c3791` assigned hosted runners and executed repository code. `Rust contracts` job `102692565837` passed Python contracts, formatting, and the complete locked workspace tests before strict Clippy rejected `plan_explicit_screen_area_override` and `plan_explicit_screen_area_cleanup` as dead code. `Production coverage` job `102692565938` passed measurement, diagnostics publication, and exact enforcement. This is a source RED, not a queue or coverage failure. + +The successor contract therefore requires: - `WebDriverBidiScreenArea` to remain the typed width/height representation derived from validated screen metrics; - an opaque `WebDriverBidiScreenAreaOwnership` carrying the exact context with no public mint constructor in the adapter; -- `SetScreenArea`, `ResetScreenArea`, and both explicit planners to require that ownership witness rather than a raw context identifier; +- `SetScreenArea` and `ResetScreenArea` to carry that ownership witness rather than a raw context identifier; +- no public explicit screen-area planner until the Browser Session ownership mint path and consuming integration exist; - no screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled; - no media-feature reset; - no color-depth field in the screen-area value object; and - continued fail-closed complete Screen admission. -The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That was corrected before acceptance: deleting a useful standard capability is not necessary when its mutation authority can instead be represented explicitly and made non-caller-mintable. +The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That remains unnecessary: the typed protocol vocabulary can stay dormant without exposing a callable dead planner or widening mutation authority. Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence. A command intent or acknowledgement is never substituted for apply → page-observed post-condition → interaction/outcome → owned cleanup/destruction → post-cleanup observation.