Skip to content
Closed
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
4 changes: 3 additions & 1 deletion src/core/mxc-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ available to feed a policy: [`available_tools_policy`] (PATH + tool/SDK env
dirs), [`user_profile_policy`], and [`temporary_files_policy`].

[`platform_support`] is the Rust port of `getPlatformSupport` β€” reports host
support and the available containment backends.
support and the available containment backends. On Windows,
`PlatformSupport::isolation_tier` reports the process-container tier selected
for the default policy.

## Live stdio + kill (streaming)

Expand Down
4 changes: 2 additions & 2 deletions src/core/mxc-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ mod sandbox;
pub use mxc_engine::policy;
pub use mxc_engine::{
available_tools_policy, build_request, platform_support, temporary_files_policy,
user_profile_policy, Error, ErrorCode, FilesystemPolicyResult, PlatformSupport, SandboxPolicy,
SandboxRequest,
user_profile_policy, Error, ErrorCode, FilesystemPolicyResult, IsolationTier, PlatformSupport,
SandboxPolicy, SandboxRequest,
};

pub use sandbox::{Output, Sandbox, StreamCloser, WaitOutcome};
Expand Down
8 changes: 8 additions & 0 deletions src/core/mxc-sdk/tests/sdk_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use mxc_sdk::{
#[cfg(target_os = "macos")]
use mxc_sdk::{spawn_sandbox, WaitOutcome};

#[cfg(target_os = "windows")]
use mxc_sdk::IsolationTier;

fn env_pairs(pairs: &[(&str, &str)]) -> Vec<(String, String)> {
pairs
.iter()
Expand All @@ -25,6 +28,8 @@ fn platform_support_reports_host() {
// Every platform this test runs on (macOS/Linux/Windows in CI) is supported.
assert!(support.is_supported, "reason: {:?}", support.reason);
assert!(!support.available_methods.is_empty());
#[cfg(not(target_os = "windows"))]
assert_eq!(support.isolation_tier, None);
}

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -215,6 +220,9 @@ fn platform_support_windows_is_processcontainer() {
support.available_methods,
vec!["processcontainer".to_string()]
);
let _: IsolationTier = support
.isolation_tier
.expect("Windows probe should select an isolation tier");
}

#[test]
Expand Down
5 changes: 3 additions & 2 deletions src/core/mxc_engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
//! - [`run`] / [`resolve_runner`] (Windows) β€” run-to-completion backend
//! selection and execution.
//! - [`run_state_aware`] β€” state-aware lifecycle backend resolution + dispatch.
//! - [`platform_support`] / [`PlatformSupport`] β€” host support detection.
//! - [`platform_support`] / [`PlatformSupport`] / [`IsolationTier`] β€” host
//! support detection.
//! - [`Error`] / [`ErrorCode`] β€” the crate-owned error facade over
//! `wxc_common`'s internal error type.

Expand All @@ -35,7 +36,7 @@ mod run;
mod state_aware;

pub use error::{Error, ErrorCode};
pub use platform::{platform_support, PlatformSupport};
pub use platform::{platform_support, IsolationTier, PlatformSupport};
pub use policy::{
available_tools_policy, build_request, temporary_files_policy, user_profile_policy,
FilesystemPolicyResult, SandboxPolicy, SandboxRequest,
Expand Down
52 changes: 48 additions & 4 deletions src/core/mxc_engine/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
//! `dispatch.rs`, so both the public SDK and the executor binaries can share a
//! single implementation.

#[cfg(target_os = "windows")]
use appcontainer_common::fallback_detector::{self, IsolationTier as BackendIsolationTier};
#[cfg(target_os = "windows")]
use wxc_common::models::ContainerPolicy;

/// Platform support information β€” the Rust analogue of the SDK
/// `PlatformSupport` type.
#[derive(Debug, Clone, Default)]
Expand All @@ -23,14 +28,28 @@ pub struct PlatformSupport {
/// Containment backends available on this host, by wire name
/// (e.g. `"seatbelt"`, `"bubblewrap"`, `"processcontainer"`).
pub available_methods: Vec<String>,
/// Isolation tier selected for the default Windows process-container policy.
///
/// `None` on non-Windows hosts or when the Windows capability probe fails.
pub isolation_tier: Option<IsolationTier>,
}

/// Windows process-container isolation tier selected by the runtime probe.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IsolationTier {
/// BaseContainer via `Experimental_CreateProcessInSandbox`.
BaseContainer,
/// AppContainer with BFS filesystem isolation.
AppContainerBfs,
/// AppContainer with host DACL augmentation.
AppContainerDacl,
}

/// Detect MXC support on the current host.
///
/// Mirrors the SDK's `getPlatformSupport`, restricted to the backends the
/// `mxc-sdk` library can actually run. On Windows the isolation tier and UI
/// capabilities come from the in-process fallback probe rather than a
/// `wxc-exec --probe` subprocess.
/// Mirrors the SDK's `getPlatformSupport`. Available methods are restricted to
/// the backends this crate can run. On Windows the isolation tier comes from the
/// in-process fallback probe rather than a `wxc-exec --probe` subprocess.
pub fn platform_support() -> PlatformSupport {
#[cfg(target_os = "macos")]
{
Expand Down Expand Up @@ -68,9 +87,18 @@ pub fn platform_support() -> PlatformSupport {

#[cfg(target_os = "windows")]
{
let isolation_tier = fallback_detector::detect(&ContainerPolicy::default(), true)
.ok()
.map(|decision| match decision.tier {
BackendIsolationTier::BaseContainer => IsolationTier::BaseContainer,
BackendIsolationTier::AppContainerBfs => IsolationTier::AppContainerBfs,
BackendIsolationTier::AppContainerDacl => IsolationTier::AppContainerDacl,
});

PlatformSupport {
is_supported: true,
available_methods: vec!["processcontainer".to_string()],
isolation_tier,
..Default::default()
}
}
Expand Down Expand Up @@ -98,3 +126,19 @@ fn command_succeeds(program: &str, args: &[&str]) -> bool {
.map(|s| s.success())
.unwrap_or(false)
}

#[cfg(all(test, target_os = "windows"))]
mod tests {
use super::*;

#[test]
fn base_container_tier_matches_probe() {
let isolation_tier = platform_support()
.isolation_tier
.expect("Windows probe should select an isolation tier");
assert_eq!(
isolation_tier == IsolationTier::BaseContainer,
appcontainer_common::fallback_detector::is_base_container_usable()
);
}
}
Loading