Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -9,6 +9,7 @@ All notable changes to OriginWeave are documented in this file. The format follo
- Rust workspace for independently reusable core, policy, destination, network, TLS, resource, and evidence modules.
- 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.
- 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.
- Deterministic fail-closed policy evaluation for untrusted instructions, origin grants, crawler restrictions, execution-mode and purpose consistency, approvals, and brokered secrets.
Expand Down
30 changes: 24 additions & 6 deletions crates/originweave-core/src/browser_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,21 +293,29 @@ impl BrowserProtocolAdapterDescriptor {
/// Validate all adapter metadata prerequisites for one immediate browser operation.
///
/// Validation is intentionally ordered and fail closed: the exact
/// OriginWeave Protocol generation is checked first, then the supplied
/// runtime protocol/browser revisions, then 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 browser or Agent authority and does not
/// authenticate the caller supplying runtime revision evidence.
/// OriginWeave Protocol generation is checked first, then the caller-supplied
/// runtime protocol family, then the supplied runtime 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
/// browser or Agent authority and does not authenticate or attest the caller
/// supplying runtime metadata.
pub fn validate_use(
&self,
required_originweave_protocol_version: OriginWeaveProtocolVersion,
runtime_kind: BrowserProtocolKind,
runtime_protocol_revision: &str,
runtime_browser_revision: &str,
required_capability: BrowserProtocolCapability,
) -> Result<ValidatedBrowserProtocolUse, BrowserProtocolUseValidationError> {
self.require_originweave_protocol_version(required_originweave_protocol_version)
.map_err(BrowserProtocolUseValidationError::ProtocolVersion)?;
if self.kind != runtime_kind {
return Err(BrowserProtocolUseValidationError::ProtocolKindMismatch {
descriptor_kind: self.kind,
runtime_kind,
});
}
self.require_runtime_revisions(runtime_protocol_revision, runtime_browser_revision)
.map_err(BrowserProtocolUseValidationError::RuntimeRevision)?;
self.require_capability(required_capability)
Expand Down Expand Up @@ -484,6 +492,13 @@ impl std::error::Error for BrowserProtocolCapabilityRequirementError {}
pub enum BrowserProtocolUseValidationError {
/// The descriptor targets the wrong OriginWeave Protocol generation.
ProtocolVersion(BrowserProtocolVersionRequirementError),
/// The runtime transport reports a different protocol family than the descriptor.
ProtocolKindMismatch {
/// Browser protocol family pinned by the adapter descriptor.
descriptor_kind: BrowserProtocolKind,
/// Browser protocol family reported by the runtime transport.
runtime_kind: BrowserProtocolKind,
},
/// 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 @@ -494,6 +509,8 @@ impl fmt::Display for BrowserProtocolUseValidationError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ProtocolVersion(error) => error.fmt(formatter),
Self::ProtocolKindMismatch { .. } => formatter
.write_str("runtime browser protocol kind does not match the pinned adapter kind"),
Self::RuntimeRevision(error) => error.fmt(formatter),
Self::Capability(error) => error.fmt(formatter),
}
Expand All @@ -504,6 +521,7 @@ 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::RuntimeRevision(error) => Some(error),
Self::Capability(error) => Some(error),
}
Expand Down
33 changes: 33 additions & 0 deletions crates/originweave-core/tests/browser_protocol_use_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ fn validated_use_binds_all_required_adapter_metadata() -> Result<(), Box<dyn Err
let descriptor = descriptor()?;
let validated = descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::Navigation,
Expand Down Expand Up @@ -61,6 +62,7 @@ fn protocol_generation_mismatch_precedes_runtime_and_capability_checks()
assert_eq!(
descriptor.validate_use(
wrong_generation,
BrowserProtocolKind::ChromeDevToolsProtocol,
"runtime revision with spaces",
"browser/revision",
BrowserProtocolCapability::NetworkObservation,
Expand All @@ -75,13 +77,43 @@ fn protocol_generation_mismatch_precedes_runtime_and_capability_checks()
Ok(())
}

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

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

assert_eq!(
error,
Err(BrowserProtocolUseValidationError::ProtocolKindMismatch {
descriptor_kind: BrowserProtocolKind::WebDriverBiDi,
runtime_kind: BrowserProtocolKind::ChromeDevToolsProtocol,
})
);
let error = error.err().ok_or("expected protocol kind mismatch")?;
assert_eq!(
error.to_string(),
"runtime browser protocol kind does not match the pinned adapter kind"
);
assert!(error.source().is_none());
Ok(())
}

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

assert_eq!(
descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
"webdriver-bidi-wd-2026-07-01",
BROWSER_REVISION,
BrowserProtocolCapability::NetworkObservation,
Expand All @@ -100,6 +132,7 @@ fn undeclared_capability_cannot_produce_validated_use() -> Result<(), Box<dyn Er
assert_eq!(
descriptor.validate_use(
ORIGINWEAVE_PROTOCOL_VERSION,
BrowserProtocolKind::WebDriverBiDi,
PROTOCOL_REVISION,
BROWSER_REVISION,
BrowserProtocolCapability::NetworkObservation,
Expand Down
Loading