Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b521bbc
test(browser): require runtime adapter version binding
seonghobae Aug 12, 2026
79fbb1f
test(browser): narrow runtime adapter version contract
seonghobae Aug 12, 2026
6db44cb
feat(browser): bind runtime adapter version
seonghobae Aug 12, 2026
d2ef3b5
test(browser): pass runtime adapter version
seonghobae Aug 12, 2026
1ef8d0c
test(evidence): pass validated runtime adapter version
seonghobae Aug 12, 2026
219ff85
style(browser): apply canonical rustfmt
seonghobae Aug 12, 2026
f368a4e
docs(changelog): record runtime adapter version binding
seonghobae Aug 12, 2026
2e0404e
test(core): require same-call browser protocol dispatch validation
seonghobae Aug 12, 2026
decc241
test(core): share dispatch callback monomorphization
seonghobae Aug 12, 2026
ff5a801
feat(core): gate protocol dispatch on current runtime metadata
seonghobae Aug 12, 2026
d6a8459
feat(core): expose validated protocol dispatch boundary
seonghobae Aug 12, 2026
37dc70d
docs: record validated protocol dispatch boundary
seonghobae Aug 12, 2026
1218808
style(core): apply canonical dispatch test formatting
seonghobae Aug 12, 2026
3c23d10
refactor(core): make validated dispatch an adapter descriptor method
seonghobae Aug 12, 2026
043ea96
refactor(core): keep dispatch method on adapter descriptor
seonghobae Aug 12, 2026
570b4d0
test(core): dispatch through adapter descriptor method
seonghobae Aug 12, 2026
9fd91db
refactor(core): bind dispatch to bounded runtime metadata
seonghobae Aug 12, 2026
8675dc3
test(core): require context-bound protocol dispatch
seonghobae Aug 12, 2026
bb571f0
style(core): apply canonical dispatch test formatting
seonghobae Aug 12, 2026
c25a060
test(core): cover context dispatch denial boundaries
seonghobae Aug 12, 2026
15a837a
feat(core): revalidate browser context ownership
seonghobae Aug 12, 2026
5c92e6d
feat(core): gate protocol dispatch on current context
seonghobae Aug 12, 2026
e33bf68
feat(core): export context protocol dispatch error
seonghobae Aug 12, 2026
4a42f03
style(core): apply canonical protocol dispatch formatting
seonghobae Aug 12, 2026
3e44bda
docs(changelog): record context-bound protocol dispatch
seonghobae Aug 12, 2026
955373a
test(core): match canonical adapter-version error text
seonghobae Aug 12, 2026
aba4a7c
test(core): require bounded context dispatch target value
seonghobae Aug 12, 2026
58e0b5c
feat(core): add bounded browser context dispatch target
seonghobae Aug 12, 2026
9ec83fd
feat(core): export browser context dispatch target
seonghobae Aug 12, 2026
beef399
style(core): apply canonical context dispatch formatting
seonghobae Aug 12, 2026
3850bf0
style(core): apply canonical dispatch export formatting
seonghobae Aug 12, 2026
48ec0a3
test(core): require browser context origin binding
seonghobae Aug 12, 2026
34993ea
style(core): apply canonical context origin test formatting
seonghobae Aug 12, 2026
2e799ee
feat(core): bind current browser context origin
seonghobae Aug 12, 2026
4f5e9b0
test(core): make controlled origin parsing error-compatible
seonghobae Aug 12, 2026
05c8834
test(core): require current browser context origin
seonghobae Aug 12, 2026
dae6566
test(core): apply canonical origin revalidation formatting
seonghobae Aug 12, 2026
61485d0
feat(core): revalidate current browser context origin
seonghobae Aug 12, 2026
1eae129
style(core): apply canonical context-origin formatting
seonghobae Aug 12, 2026
4d5e5ae
merge: align runtime adapter version binding with current validation …
seonghobae Aug 15, 2026
ff18aaf
merge: align runtime dispatch validation with current adapter-version…
seonghobae Aug 15, 2026
1b08424
merge: align browser-context protocol dispatch with current runtime v…
seonghobae Aug 15, 2026
481ea74
merge: align browser context origin binding with current protocol dis…
seonghobae Aug 15, 2026
67e82ca
merge: align browser context origin revalidation with current binding
seonghobae Aug 15, 2026
2ed5dfb
fix(core): preserve browser authority retirement on stack alignment
seonghobae Aug 16, 2026
e2c24bf
merge: align browser origin binding with authority retirement
seonghobae Aug 16, 2026
9419430
merge: preserve browser retirement in origin revalidation
seonghobae Aug 16, 2026
36bac73
merge: align runtime adapter version binding with current validation …
seonghobae Aug 19, 2026
b906dec
merge: align runtime dispatch validation with current adapter-version…
seonghobae Aug 19, 2026
170ce4c
merge: align context protocol dispatch with current runtime dispatch
seonghobae Aug 19, 2026
f474174
merge: align context origin binding with current protocol dispatch
seonghobae Aug 19, 2026
c9e6319
merge: align origin revalidation with current origin binding
seonghobae Aug 19, 2026
de57fd8
Merge pull request #115 from ContextualWisdomLab/feat/browser-protoco…
seonghobae Aug 26, 2026
d7cc599
docs: record browser context origin binding
seonghobae Aug 26, 2026
6996e6f
docs: record context origin revalidation
seonghobae Aug 26, 2026
41d564b
Merge pull request #116 from ContextualWisdomLab/feat/browser-context…
seonghobae Aug 26, 2026
981caf6
Merge pull request #117 from ContextualWisdomLab/feat/browser-context…
seonghobae Aug 26, 2026
734210a
Merge remote-tracking branch 'origin/feat/browser-protocol-runtime-ad…
seonghobae Aug 26, 2026
feee434
Merge pull request #118 from ContextualWisdomLab/feat/browser-context…
seonghobae Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to OriginWeave are documented in this file. The format follo
- Versioned browser-protocol adapter metadata that distinguishes WebDriver BiDi from pinned CDP, binds bounded adapter/browser revision tokens to an explicit duplicate-free capability set, normalizes capability-set identity independently of caller ordering, and exposes typed fail-closed capability requirements without granting browser, action, network, or secret authority by protocol kind alone.
- Canonical OriginWeave protocol-version parsing for exact `originweave/<major>.<minor>` syntax, with typed fail-closed rejection of malformed, ambiguous, overflowed, or noncanonical serialized generations; parsing does not negotiate compatibility or grant adapter authority.
- Atomic browser-protocol use validation that requires the exact OriginWeave protocol generation, caller-supplied runtime protocol family, exact pinned runtime protocol/browser revisions, and an explicitly declared capability in deterministic fail-closed order before producing non-cloneable validation evidence; this metadata proof does not authenticate the adapter or grant browser/Agent authority.
- Runtime browser-adapter version binding at the atomic protocol-use boundary: the caller-supplied bounded adapter-version token must exactly match the reviewed descriptor version before runtime revision or capability checks can succeed, preventing adapter-build drift from silently reusing otherwise matching protocol/browser metadata without authenticating or attesting the adapter process.
- Credential-safe browser-protocol validation evidence that copies only the already validated protocol family, OriginWeave generation, adapter version, pinned protocol/browser revisions, and exact capability into cloneable audit metadata without recreating the non-cloneable validation prerequisite or granting browser/Agent authority.
- Canonical HTTPS and loopback-origin boundary with case-normalized schemes and hosts, default-port normalization, IPv4/IPv6 handling, browser-special numeric-host rejection, and explicit malformed-input errors.
- Typed browser actions, capabilities, risk classes, execution modes, robots decisions, secret-delivery contracts, immutable canonical action-intent digests, and intent-bound approval scopes.
Expand Down
23 changes: 21 additions & 2 deletions crates/originweave-core/src/browser_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ impl BrowserProtocolAdapterDescriptor {
///
/// Validation is intentionally ordered and fail closed: the exact
/// OriginWeave Protocol generation is checked first, then the caller-supplied
/// runtime protocol family, then the supplied runtime protocol/browser
/// runtime protocol family, runtime adapter version, protocol/browser
/// revisions, and finally the required adapter capability. Success returns
/// a non-cloneable value that a later trusted transport can consume as proof
/// that these metadata prerequisites were checked together. It is not
Expand All @@ -304,6 +304,7 @@ impl BrowserProtocolAdapterDescriptor {
&self,
required_originweave_protocol_version: OriginWeaveProtocolVersion,
runtime_kind: BrowserProtocolKind,
runtime_adapter_version: &str,
runtime_protocol_revision: &str,
runtime_browser_revision: &str,
required_capability: BrowserProtocolCapability,
Expand All @@ -316,6 +317,12 @@ impl BrowserProtocolAdapterDescriptor {
runtime_kind,
});
}
if !metadata_token_is_valid(runtime_adapter_version) {
return Err(BrowserProtocolUseValidationError::InvalidAdapterVersion);
}
if self.adapter_version != runtime_adapter_version {
return Err(BrowserProtocolUseValidationError::AdapterVersionMismatch);
}
self.require_runtime_revisions(runtime_protocol_revision, runtime_browser_revision)
.map_err(BrowserProtocolUseValidationError::RuntimeRevision)?;
self.require_capability(required_capability)
Comment on lines 317 to 328

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: validate_use gains required parameter, all callers updated

validate_use now takes a required runtime_adapter_version. Every caller in the workspace was updated; the only non-test consumer is dispatch_if_runtime_matches. No production caller is left passing the old argument list.

(Refers to this code)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Expand Down Expand Up @@ -499,6 +506,10 @@ pub enum BrowserProtocolUseValidationError {
/// Browser protocol family reported by the runtime transport.
runtime_kind: BrowserProtocolKind,
},
/// The runtime adapter-version token was malformed.
InvalidAdapterVersion,
/// The runtime adapter version differs from the pinned descriptor version.
AdapterVersionMismatch,
/// The supplied runtime protocol or browser revision is invalid or has drifted.
RuntimeRevision(BrowserProtocolRuntimeRequirementError),
/// The descriptor does not explicitly declare the required capability.
Expand All @@ -511,6 +522,12 @@ impl fmt::Display for BrowserProtocolUseValidationError {
Self::ProtocolVersion(error) => error.fmt(formatter),
Self::ProtocolKindMismatch { .. } => formatter
.write_str("runtime browser protocol kind does not match the pinned adapter kind"),
Self::InvalidAdapterVersion => formatter.write_str(
"runtime browser adapter version must be a bounded ASCII metadata token",
),
Self::AdapterVersionMismatch => formatter.write_str(
"runtime browser adapter version does not match the pinned adapter version",
),
Self::RuntimeRevision(error) => error.fmt(formatter),
Self::Capability(error) => error.fmt(formatter),
}
Expand All @@ -521,7 +538,9 @@ impl std::error::Error for BrowserProtocolUseValidationError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ProtocolVersion(error) => Some(error),
Self::ProtocolKindMismatch { .. } => None,
Self::ProtocolKindMismatch { .. }
| Self::InvalidAdapterVersion
| Self::AdapterVersionMismatch => None,
Self::RuntimeRevision(error) => Some(error),
Self::Capability(error) => Some(error),
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::error::Error;

use originweave_core::{
BrowserProtocolAdapterDescriptor, BrowserProtocolCapability, BrowserProtocolKind,
BrowserProtocolUseValidationError, OriginWeaveProtocolVersion,
};

const ORIGINWEAVE_PROTOCOL_VERSION: OriginWeaveProtocolVersion =
OriginWeaveProtocolVersion::new(0, 1);
const ADAPTER_VERSION: &str = "originweave-bidi-v1";
const PROTOCOL_REVISION: &str = "webdriver-bidi-wd-2026-06-01";
const BROWSER_REVISION: &str = "chromium-r1639810";

fn descriptor() -> Result<BrowserProtocolAdapterDescriptor, Box<dyn Error>> {
Ok(BrowserProtocolAdapterDescriptor::new(
BrowserProtocolKind::WebDriverBiDi,
ORIGINWEAVE_PROTOCOL_VERSION,
ADAPTER_VERSION,
PROTOCOL_REVISION,
BROWSER_REVISION,
&[BrowserProtocolCapability::Navigation],
)?)
}

#[test]
fn runtime_adapter_version_is_bound_into_atomic_use_validation() -> Result<(), Box<dyn Error>> {
let descriptor = descriptor()?;

let validated = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
ADAPTER_VERSION,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::Navigation,
)?;

assert_eq!(validated.adapter_version(), ADAPTER_VERSION);
Ok(())
}

#[test]
fn runtime_adapter_version_mismatch_precedes_revision_and_capability_checks()
-> Result<(), Box<dyn Error>> {
let descriptor = descriptor()?;

let error = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
"originweave-bidi-v2",
"runtime revision with spaces",
"browser/revision",
BrowserProtocolCapability::NetworkObservation,
);

assert_eq!(
error,
Err(BrowserProtocolUseValidationError::AdapterVersionMismatch)
);
let error = error.err().ok_or("expected adapter version mismatch")?;
assert_eq!(
error.to_string(),
"runtime browser adapter version does not match the pinned adapter version"
);
assert!(error.source().is_none());
Ok(())
}

#[test]
fn malformed_runtime_adapter_version_fails_closed_before_revision_checks()
-> Result<(), Box<dyn Error>> {
let descriptor = descriptor()?;

let error = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
"runtime adapter/version",
"runtime revision with spaces",
"browser/revision",
BrowserProtocolCapability::NetworkObservation,
);

assert_eq!(
error,
Err(BrowserProtocolUseValidationError::InvalidAdapterVersion)
);
let error = error.err().ok_or("expected invalid adapter version")?;
assert_eq!(
error.to_string(),
"runtime browser adapter version must be a bounded ASCII metadata token"
);
assert!(error.source().is_none());
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fn validated_use_binds_all_required_adapter_metadata() -> Result<(), Box<dyn Err
let validated = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
ADAPTER_VERSION,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::Navigation,
Expand Down Expand Up @@ -63,6 +64,7 @@ fn protocol_generation_mismatch_precedes_runtime_and_capability_checks()
descriptor.validate_use(
wrong_generation,
BrowserProtocolKind::ChromeDevToolsProtocol,
"runtime adapter/version",
"runtime revision with spaces",
"browser/revision",
BrowserProtocolCapability::NetworkObservation,
Expand All @@ -78,13 +80,14 @@ fn protocol_generation_mismatch_precedes_runtime_and_capability_checks()
}

#[test]
fn runtime_protocol_kind_mismatch_precedes_revision_and_capability_checks()
fn runtime_protocol_kind_mismatch_precedes_adapter_revision_and_capability_checks()
-> Result<(), Box<dyn Error>> {
let descriptor = descriptor()?;

let error = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::ChromeDevToolsProtocol,
"runtime adapter/version",
"runtime revision with spaces",
"browser/revision",
BrowserProtocolCapability::NetworkObservation,
Expand Down Expand Up @@ -114,6 +117,7 @@ fn runtime_revision_validation_precedes_capability_check() -> Result<(), Box<dyn
descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
ADAPTER_VERSION,
"webdriver-bidi-wd-2026-07-01",
BROWSER_REVISION,
BrowserProtocolCapability::NetworkObservation,
Expand All @@ -133,6 +137,7 @@ fn undeclared_capability_cannot_produce_validated_use() -> Result<(), Box<dyn Er
descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
ADAPTER_VERSION,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::NetworkObservation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fn records_exact_metadata_from_one_validated_browser_protocol_use() -> Result<()
let validated = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
ADAPTER_VERSION,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::SemanticObservation,
Expand All @@ -50,18 +51,21 @@ fn records_exact_metadata_from_one_validated_browser_protocol_use() -> Result<()
#[test]
fn evidence_is_owned_audit_metadata_not_reusable_validation_authority() -> Result<(), Box<dyn Error>>
{
let cdp_adapter_version = "originweave-cdp-v1";
let cdp_protocol_revision = "cdp-1-3-r1639810";
let descriptor = BrowserProtocolAdapterDescriptor::new(
BrowserProtocolKind::ChromeDevToolsProtocol,
ORIGINWEAVE_PROTOCOL_VERSION,
"originweave-cdp-v1",
"cdp-1-3-r1639810",
cdp_adapter_version,
cdp_protocol_revision,
BROWSER_REVISION,
&[BrowserProtocolCapability::NetworkObservation],
)?;
let validated = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::ChromeDevToolsProtocol,
"cdp-1-3-r1639810",
cdp_adapter_version,
cdp_protocol_revision,
BROWSER_REVISION,
BrowserProtocolCapability::NetworkObservation,
)?;
Expand Down
Loading