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
6 changes: 3 additions & 3 deletions crates/openshell-driver-mxc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub use relay::RelayHandle;
pub use policy::{EmbeddedPolicyMapper, MapCtx, MapError, MappedConfig, PolicyMapper};
#[cfg(target_os = "windows")]
pub use policy_map::{
DEFAULT_COMMAND, DEFAULT_CONTAINMENT, DEFAULT_MXC_VERSION, LossItem, MxcMappingOptions,
MxcMappingResult, OPEN_SHELL_SUPERSET_GAPS, SplitPolicyResult, build_loss_report, map_to_mxc,
render_readme, split_policy,
DEFAULT_COARSE_MXC_VERSION, DEFAULT_COMMAND, DEFAULT_CONTAINMENT, DEFAULT_MXC_VERSION,
LossItem, MxcMappingOptions, MxcMappingResult, OPEN_SHELL_SUPERSET_GAPS, SplitPolicyResult,
build_loss_report, map_to_mxc, render_readme, split_policy,
};
14 changes: 8 additions & 6 deletions crates/openshell-driver-mxc/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
//! the standalone `openshell-policy-mapper` crate). This file defines the trait
//! seam plus:
//!
//! - [`EmbeddedPolicyMapper`] — the **primary** impl. Calls
//! [`crate::policy_map::map_to_mxc`] directly on the typed `SandboxPolicy`
//! proto (no YAML bridge), extracts the MXC filesystem shares, normalizes
//! their paths to Windows form, and rejects the create on any `error`-severity
//! loss.
//! - [`EmbeddedPolicyMapper`] — the **primary** impl. Calls the coarse mapper or
//! governed-egress split directly on the typed `SandboxPolicy` proto (no YAML
//! bridge), extracts the MXC filesystem/UI fragment, normalizes paths, and
//! rejects the create on any `error`-severity loss. The generated mapping JSON
//! is an intermediate representation: live requests are rebuilt by
//! [`crate::mxc`] using its active schema version.
//!
//! **Rule: never silently drop policy.** Unmappable rules surface as
//! `MapError::Unsupported` and are rejected by `CreateSandbox` before lifecycle side effects.
Expand Down Expand Up @@ -181,7 +182,8 @@ impl PolicyMapper for EmbeddedPolicyMapper {
// Map directly off the typed proto. The default MXC driver path runs
// an isolation session, so use that containment: its network branch
// yields an `error` loss for any host allowlist, which rejects
// network policy below.
// network policy below. This coarse JSON is never sent to wxc-exec;
// only the extracted filesystem/UI policy enters the live request.
let opts = crate::policy_map::MxcMappingOptions {
containment: ctx.containment.clone(),
container_id: ctx.sandbox_id.clone(),
Expand Down
14 changes: 12 additions & 2 deletions crates/openshell-driver-mxc/src/policy_map/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,18 @@ use super::loss::{LossItem, add_loss};
/// not supply a real workload command.
pub const DEFAULT_COMMAND: &str = "sh -lc \"echo OpenShell policy mapped to MXC; replace process.commandLine before running a real workload\"";

/// Default MXC schema version emitted in `version`.
pub const DEFAULT_MXC_VERSION: &str = "0.7.0-alpha";
/// Default schema for the standalone coarse mapper's host-list config.
///
/// This is deliberately independent from [`crate::mxc::MXC_SCHEMA_VERSION`]:
/// the coarse artifact uses the MXC 0.7 `allowedHosts` shape, while live driver
/// requests and the governed-egress split use MXC 0.8 directional networking.
pub const DEFAULT_COARSE_MXC_VERSION: &str = "0.7.0-alpha";

/// Compatibility name for [`DEFAULT_COARSE_MXC_VERSION`].
///
/// This value belongs only to [`super::map_to_mxc`] output. It is not the
/// schema version used for live `wxc-exec` requests.
pub const DEFAULT_MXC_VERSION: &str = DEFAULT_COARSE_MXC_VERSION;

/// Default MXC containment backend for the coarse mapping.
pub const DEFAULT_CONTAINMENT: &str = "bubblewrap";
Expand Down
9 changes: 5 additions & 4 deletions crates/openshell-driver-mxc/src/policy_map/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use openshell_core::proto::{
use serde_json::{Value, json};

use super::config::{
DEFAULT_COMMAND, DEFAULT_CONTAINMENT, DEFAULT_MXC_VERSION, add_backend_network_loss,
DEFAULT_COARSE_MXC_VERSION, DEFAULT_COMMAND, DEFAULT_CONTAINMENT, add_backend_network_loss,
add_backend_specific_config, default_enforcement_mode, filesystem_default_deny_message,
};
use super::loss::{LossItem, add_loss};
Expand All @@ -27,8 +27,9 @@ use crate::mxc::MXC_SCHEMA_VERSION;
/// coarse map (e.g. `proxy_redirect`) are reserved for the governed-egress split.
#[derive(Clone, Debug)]
pub struct MxcMappingOptions {
/// MXC schema version written into coarse-map output. The governed-egress
/// split uses the driver's MXC 0.8 schema.
/// Caller-selectable schema version written only into standalone coarse-map
/// output. The governed-egress split and live driver requests instead use
/// [`MXC_SCHEMA_VERSION`].
pub mxc_version: String,
/// MXC containment backend.
pub containment: String,
Expand All @@ -52,7 +53,7 @@ pub struct MxcMappingOptions {
impl Default for MxcMappingOptions {
fn default() -> Self {
Self {
mxc_version: DEFAULT_MXC_VERSION.to_owned(),
mxc_version: DEFAULT_COARSE_MXC_VERSION.to_owned(),
containment: DEFAULT_CONTAINMENT.to_owned(),
command: DEFAULT_COMMAND.to_owned(),
container_id: "openshell-policy".to_owned(),
Expand Down
14 changes: 11 additions & 3 deletions crates/openshell-driver-mxc/src/policy_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@
//! policy is flattened into an MXC host allowlist (`network.allowedHosts`),
//! and anything MXC cannot express (ports, protocol, L7 rules, binary scope)
//! is recorded in the loss report. Use this when MXC enforces network on its
//! own, with no `OpenShell` proxy in the loop.
//! own, with no `OpenShell` proxy in the loop. Its default schema is MXC 0.7,
//! matching that host-list shape; the caller can override the coarse target.
//! - [`split_policy`] — the *lossless* split for the Windows MXC compute
//! driver: MXC handles filesystem + containment + loopback-only egress,
//! while the full `OpenShell` network policy is preserved in a trimmed policy
//! enforced by the host CONNECT proxy.
//! enforced by the host CONNECT proxy. This path uses the live driver's MXC
//! 0.8 directional-network schema.
//!
//! The coarse mapper's schema version describes its generated artifact, not the
//! live driver's operating schema. The embedded driver may use a coarse mapping
//! as an intermediate policy translation but does not send that JSON to MXC.
//!
//! The report/loss-report helpers are only exercised by the example and the
//! integration tests, so the Windows lib build would otherwise warn on them;
Expand All @@ -36,7 +42,9 @@ mod loss;
mod map;
mod report;

pub use config::{DEFAULT_COMMAND, DEFAULT_CONTAINMENT, DEFAULT_MXC_VERSION};
pub use config::{
DEFAULT_COARSE_MXC_VERSION, DEFAULT_COMMAND, DEFAULT_CONTAINMENT, DEFAULT_MXC_VERSION,
};
pub use loss::{LossItem, OPEN_SHELL_SUPERSET_GAPS};
pub use map::{MxcMappingOptions, MxcMappingResult, SplitPolicyResult, map_to_mxc, split_policy};
pub use report::{build_loss_report, render_readme};
5 changes: 4 additions & 1 deletion crates/openshell-driver-mxc/src/policy_map/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use serde_json::{Value, json};

use super::loss::{LossItem, OPEN_SHELL_SUPERSET_GAPS, summarize_missing_mxc};

/// Build the structured `loss-report.json` value.
/// Build the structured `loss-report.json` value for a generated mapper artifact.
///
/// `target.schemaVersion` describes that artifact's caller-selected schema. It
/// must not be interpreted as the live MXC driver's request schema.
pub fn build_loss_report(
source_policy: &str,
generated_config: &str,
Expand Down
24 changes: 22 additions & 2 deletions crates/openshell-driver-mxc/tests/policy_mapper_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use openshell_core::proto::{
NetworkPolicyRule, ProcessPolicy, SandboxPolicy, UiClipboardAccess, UiPolicy,
};
use openshell_driver_mxc::{
EmbeddedPolicyMapper, MapCtx, MapError, MxcMappingOptions, PolicyMapper, map_to_mxc,
split_policy,
DEFAULT_COARSE_MXC_VERSION, DEFAULT_MXC_VERSION, EmbeddedPolicyMapper, MapCtx, MapError,
MxcMappingOptions, PolicyMapper, map_to_mxc, split_policy,
};
use openshell_policy::{serialize_sandbox_policy, validate_sandbox_policy};
use serde_json::Value;
Expand Down Expand Up @@ -132,6 +132,26 @@ fn assert_single_loss(

// ─── QUADRANT A: mappable fields, assert exact MXC output ───────────────────

/// The standalone coarse mapper and live governed-egress path intentionally
/// target different schema shapes. Keep the compatibility constant scoped to
/// the coarse artifact and prevent either side from silently drifting.
#[test]
fn a_schema_versions_match_their_distinct_network_shapes() {
let policy = SandboxPolicy::default();
let coarse = map_to_mxc(&policy, &default_opts()).config;
assert_eq!(DEFAULT_MXC_VERSION, DEFAULT_COARSE_MXC_VERSION);
assert_eq!(coarse["version"], DEFAULT_COARSE_MXC_VERSION);
assert!(coarse["network"].get("allowedHosts").is_some());
assert!(coarse["network"].get("egress").is_none());

let governed = split_policy(&policy, &pc_split_opts())
.expect("governed split must exist when a proxy redirect is configured")
.mxc_config;
assert_eq!(governed["version"], "0.8.0-alpha");
assert!(governed["network"].get("allowedHosts").is_none());
assert!(governed["network"].get("egress").is_some());
}

/// filesystem.read_write → readwritePaths verbatim, order preserved.
#[test]
fn a_rw_paths_verbatim() {
Expand Down
Loading