Repository navigation
Add caller-owned policy preparation - #1718
Ross Nichols (rossnichols) wants to merge 5 commits into
Conversation
Return structured policy refusals and prepare restricted candidates without creation. Preserve V1 creation APIs; callers own acceptance, storage and retries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
🟡 Changes recommended
The validation gate can incorrectly pass when native-preparation theory results are absent because passing pure-storage rows with the same method names satisfy its checks.
1 open issue
What changed in this PR
Implements the caller-owned policy preparation design from #1635 for Windows ProcessContainer. Applications can inspect proposed permission reductions before submitting their chosen request through ordinary strict creation.
Changes:
- Adds V1.Dev preparation APIs and candidate-storage helpers across Rust, .NET, and Node.
- Preserves structured native policy observations across SDK boundaries while keeping resource details out of default error formatting.
- Adds compatibility, ownership, preparation, and enforcement coverage, with scheduled validation checks and updated documentation.
| File | Description |
|---|---|
src/mxc-sdk/tests/streaming_processcontainer.rs |
Tests preparation, acceptance, filesystem enforcement, and request reuse. |
src/mxc-sdk/tests/dev_compatibility.rs |
Checks existing V1.Dev options and creation signatures. |
src/mxc-sdk/src/lib.rs |
Exposes bounded observation decoding for FFI. |
src/mxc-sdk/src/dev.rs |
Adds preparation APIs, exports, and storage helpers. |
src/mxc-sdk/src/core/process_security_environment_spec/README.md |
Documents policy-result schema provenance and regeneration. |
src/mxc-sdk/src/core/process_security_environment_policy_result/mod.rs |
Registers generated policy-result bindings. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/value_kind_generated.rs |
Adds generated value-kind constants. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/resource_kind_generated.rs |
Adds generated resource-kind constants. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/required_action_generated.rs |
Adds generated restriction-action constants. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/policy_result_version_generated.rs |
Adds generated result-version constants. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/policy_result_limit_generated.rs |
Adds generated diagnostic limits. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/policy_result_flags_generated.rs |
Adds generated result flags. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/policy_outcome_generated.rs |
Adds generated policy outcomes. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/policy_access_generated.rs |
Adds generated filesystem access values. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/failure_reason_generated.rs |
Adds generated refusal reasons. |
src/mxc-sdk/src/core/process_security_environment_policy_result/experimental_process_security_environment_policy_result/failure_class_generated.rs |
Adds generated policy-failure classes. |
src/mxc-sdk/src/core/mxc_engine/policy_preparation.rs |
Validates and routes preparation to ProcessContainer. |
src/mxc-sdk/src/core/mxc_engine/policy_preparation_tests.rs |
Tests invalid inputs, limits, and safe error text. |
src/mxc-sdk/src/core/mxc_engine/mod.rs |
Registers engine preparation support. |
src/mxc-sdk/src/core/mxc_engine/error.rs |
Documents and tests structured error preservation. |
src/mxc-sdk/src/core/mxc_engine/dispatch.rs |
Uses shared structured spawn-error conversion. |
src/mxc-sdk/src/core/mxc_common/splice.rs |
Preserves unchanged JSON members verbatim. |
src/mxc-sdk/src/core/mxc_common/script_runner.rs |
Emits structured backend error envelopes. |
src/mxc-sdk/src/core/mxc_common/mxc_error.rs |
Redacts diagnostic details and restores structured errors. |
src/mxc-sdk/src/core/mxc_common/mod.rs |
Registers shared observation and preparation models. |
src/mxc-sdk/src/core/mod.rs |
Registers the private policy-result module. |
src/mxc-sdk/src/backends/process_container/common/working_directory.rs |
Adds fallible working-directory resolution for preparation. |
src/mxc-sdk/src/backends/process_container/common/secenv_policy.rs |
Decodes bounded native results and recognizes restrictions. |
src/mxc-sdk/src/backends/process_container/common/network_policy_helpers.rs |
Shares capture-related capability selection. |
src/mxc-sdk/src/backends/process_container/common/native_capture.rs |
Allows capture initialization from an existing environment. |
src/mxc-sdk/src/backends/process_container/common/mod.rs |
Registers backend preparation modules. |
src/mxc-sdk/src/backends/process_container/common/launch_diagnostics.rs |
Adds administrative-policy refusal guidance. |
src/mxc-sdk/src/backends/process_container/common/base_container_helpers.rs |
Centralizes effective capability calculation. |
src/mxc-sdk/README.md |
Explains Rust caller-owned preparation. |
src/mxc-sdk/examples/policy_feedback.rs |
Demonstrates explicit approval, storage, and bounded retries. |
src/mxc-sdk/Cargo.toml |
Enables tests for the preparation example. |
src/ffi/mxc_ffi/tests/ffi.rs |
Checks initialization of the new error-details field. |
src/ffi/mxc_ffi/src/policy_preparation_tests.rs |
Tests FFI validation and allocation ownership. |
src/ffi/mxc_ffi/src/lib.rs |
Adds the preparation entry point and shared JSON-result handling. |
src/ffi/mxc_ffi/src/error_detail.rs |
Transports and frees structured error JSON. |
sdk/node/tests/unit/streaming-binding.test.ts |
Tests structured creation errors and cleanup. |
sdk/node/tests/unit/inprocess-run.test.ts |
Verifies creation options reject policy observations. |
sdk/node/tests/integration/windows-process-container.test.ts |
Reuses private Windows fixture creation. |
sdk/node/tests/integration/test-helpers.ts |
Adds a reusable private Windows directory helper. |
sdk/node/tests/integration/dev-api.ts |
Checks packaged preparation APIs and caller acceptance. |
sdk/node/src/v1/errors.ts |
Hides structured details from default inspection. |
sdk/node/src/v1/dev/policy-preparation.ts |
Defines preparation models and checked storage helpers. |
sdk/node/src/v1/dev/json-duplicate-keys.ts |
Detects duplicate JSON object keys. |
sdk/node/src/v1/dev/index.ts |
Exports observation helpers and the preparation API. |
sdk/node/src/bindings/streaming.ts |
Initializes complete native error structures. |
sdk/node/src/bindings/state-aware.ts |
Initializes structured lifecycle errors. |
sdk/node/src/bindings/run.ts |
Initializes complete native execution results. |
sdk/node/src/bindings/pty.ts |
Initializes structured terminal errors. |
sdk/node/src/bindings/probe.ts |
Initializes structured probe errors. |
sdk/node/src/bindings/policy-preparation.ts |
Adds asynchronous native preparation with cleanup. |
sdk/node/src/bindings/native-error.ts |
Decodes structured backend error details. |
sdk/node/README.md |
Documents preparation, storage, and sensitive error details. |
sdk/dotnet/README.md |
Documents preparation and explicit caller acceptance. |
sdk/dotnet/Microsoft.Mxc.Sdk/V1/MxcException.cs |
Adds independently owned backend details. |
sdk/dotnet/Microsoft.Mxc.Sdk/V1/Dev/PreparedPolicyRequest.cs |
Adds candidate models and checked JSON storage. |
sdk/dotnet/Microsoft.Mxc.Sdk/V1/Dev/PolicyPreparationOptions.cs |
Defines separate preparation controls. |
sdk/dotnet/Microsoft.Mxc.Sdk/V1/Dev/MxcContainer.cs |
Adds synchronous and asynchronous preparation APIs. |
sdk/dotnet/Microsoft.Mxc.Sdk/PolicyFailureValueJsonConverter.cs |
Preserves unsigned 64-bit values as decimal strings. |
sdk/dotnet/Microsoft.Mxc.Sdk/Native/NativeError.cs |
Converts native structured details into managed exceptions. |
sdk/dotnet/Microsoft.Mxc.Sdk/MxcJsonSerialization.cs |
Registers JSON types and duplicate-property validation. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/V1/V1ApiSurfaceTests.cs |
Checks preparation types and signatures. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/V1/MxcContainerTests.cs |
Tests structured probe-error transport. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/NativeErrorTests.cs |
Tests detail ownership, extraction, and safe formatting. |
sdk/dotnet/Microsoft.Mxc.Sdk.Tests/MxcExceptionTests.cs |
Verifies details survive JSON-document disposal. |
sdk/dotnet/Microsoft.Mxc.Sdk.AotSmokeTest/Program.cs |
Adds preparation and observation serialization coverage. |
scripts/ci/test-policy-preparation-test-results.ps1 |
Adds positive and negative result-check fixtures. |
scripts/ci/run_backend_validation_tests.ps1 |
Runs preparation scenarios in Windows validation. |
scripts/ci/lib/TestSuiteResults.ps1 |
Adds required-output checks for test results. |
scripts/ci/build-windows-sdk-test-bundle.ps1 |
Requires preparation test discovery in bundles. |
external/windows-sdk/ProcessSecurityEnvironment.provenance.toml |
Pins the policy-result schema source and hash. |
external/windows-sdk/ExperimentalProcessSecurityEnvironmentPolicyResult.fbs |
Defines the native refusal-diagnostics contract. |
docs/development/guides/process-container-adding-os-features.md |
Documents native diagnostics and preparation invariants. |
docs/development/build-and-test/ci-validation-infrastructure.md |
Documents preparation scenarios and validation requirements. |
docs/development/architecture/designs/1634-creation-policy-correction/README.md |
Removes the superseded prototype note. |
docs/development/architecture/designs/1634-creation-policy-correction/api.md |
Links the implemented example and SDK references. |
docs/backends/nvx/nvx.md |
Documents recovery details now exposed through managed SDKs. |
docs/api-reference/rust/v1/types.md |
Clarifies error redaction and observation extraction. |
docs/api-reference/rust/v1/README.md |
Updates the Dev API link label. |
docs/api-reference/rust/v1/api.md |
Identifies preparation in the Dev API link. |
docs/api-reference/node/v1/types.md |
Documents structured details and logging precautions. |
docs/api-reference/node/v1/README.md |
Updates the Dev API link label. |
docs/api-reference/node/v1/api.md |
Identifies preparation in the Dev API link. |
docs/api-reference/dotnet/v1/types.md |
Documents owned exception details. |
docs/api-reference/dotnet/v1/README.md |
Introduces preparation and AOT-compatible storage. |
docs/api-reference/dotnet/v1/api.md |
Identifies preparation in the Dev API link. |
Review effort: Balanced
Require each native storage theory row to pass in scheduled validation, and cover missing native rows when the pure-storage rows pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Windows-specific refusal capture and restrictive filesystem preparation require capable-host validation beyond this review environment, with a full scheduled-host run, a real governed-policy refusal, and fresh Native AOT execution still unverified.
No open issues 🎉
1 resolved since last review
Review effort: Balanced
Compile the request projection helper only on Windows. Keep injected policy tests independent of native PSEC attribute support and use canonical fixture paths when testing literal filesystem restrictions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Windows-specific refusal capture and policy enforcement remain unverified because the final candidate lacks capable-host validation through the full scheduled suite and a real governed refusal.
No open issues 🎉
Review effort: Balanced
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved issues can break the scheduled test on aliased temporary paths, hide SDK remediation guidance, and allow policy-change serialization to produce saved candidates that cannot be restored.
4 open issues
Review effort: Max
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Human assessment is needed to weigh how masking native-library loading and missing-symbol diagnostics affects troubleshooting installation and version mismatches.
No open issues 🎉
4 resolved since last review
Review effort: Max
Keep loader and missing-symbol errors actionable without exposing policy payload failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Security-sensitive Windows policy enforcement and cross-SDK ABI changes require maintainer review because the final candidate lacks governed-refusal testing, a full scheduled-host run, and fresh Native AOT publication.
No open issues 🎉
Review effort: Max

📖 Description
When Windows refuses a container request because it exceeds administrative
policy, an application needs to understand the refusal and decide whether a
more restricted request still serves its task. For example, a caller requesting
write access may be willing to accept read-only access, but MXC must not make
that acceptance decision or run the workload on its behalf.
This implements the caller-owned preparation design across Rust, .NET and Node:
supplies them, preserving the original error category, operation and HRESULT.
Resource details remain separate from ordinary error text and default
diagnostic inspection, while remediation remains visible to callers.
PolicyFailuresand separatePolicyPreparationOptions. It returns aPreparedPolicyRequestcontaining candidate JSON and ordered before/afterchanges, without creating a container or launching a workload.
chosen JSON through ordinary strict creation. Storage and merge helpers keep
observations lossless and bounded; the caller owns persistence and retry
limits.
Preparation proves supported capability, network/capture and filesystem
reductions against the current request, preserves unrelated permissions and
workload settings, and rejects unsafe or unsupported changes. Published V1
creation signatures and options remain unchanged. Creation never accepts
observations, modifies a request or retries automatically.
Native preparation is Windows ProcessContainer-only. Availability is determined
through runtime API and capture-support checks, not an inferred minimum Windows
build. Other backends cannot silently accept preparation or obtain a fallback.
SDK references, backend guidance and scheduled validation requirements are
updated alongside the implementation.
🔗 References
Refs #1634 (
feature-accepted; remains open for validation coordination).Approved design and API proposal: #1635, merged into
main.🔍 Validation
Backend tests exercise restrictive changes and unsafe observations, including
network/capture interactions, filesystem ceilings and unchanged caller inputs.
Preparation tests check that candidates and change reports are owned and that
preparation does not launch a workload. SDK tests cover error transport and
diagnostic inspection, keeping remediation visible while details remain
redacted. They also cover storage/merge bounds, duplicate change values, large
values and text, and compatibility with strict creation.
Injected backend tests use fake PSEC creation and startup attributes while
exercising strict request submission and a fixed child-process fixture.
Filesystem-preservation fixtures resolve temporary-directory aliases before
constructing literal grants; production alias-safety checks remain active.
The managed native-success rows require the established capable-host opt-in;
pure storage rows remain runnable without it. Bundle discovery requires the
native rows, and scheduled validation rejects missing or skipped required
tests. The actual managed runner was exercised both with and without opt-in;
negative discovery and result fixtures verify that omitted native rows cannot
produce a passing gate.
Executed local checks and results
srccargo fmt --all -- --checksrccargo clippy --locked -p mxc-sdk --all-targets -- -D warningssrccargo test --locked -p mxc-sdk --lib policy_TEMPandTMPset to an 8.3 short-name pathsrccargo test --locked -p mxc-sdk --lib startup_info_attaches_security_environment_attributesrccargo test -p mxc-sdk --test dev_compatibilitysdk\nodenpm testsdk\nodenpm run typecheckdotnet build .\sdk\dotnet\Microsoft.Mxc.Sdk.Tests\Microsoft.Mxc.Sdk.Tests.csproj -f net10.0 -v:q.\scripts\ci\test-policy-preparation-test-results.ps1The review-fix regressions were also run directly. From the repository root:
Result: 1 passed; duplicate properties in both stored change values are
rejected, and duplicate annotations in
RequestJsonround-trip.From
src:Result: 1 passed, with success markers for
0.9.0-alpha,1.0.0and1.1.0-alpha.The result-gate fixtures separately omit each
nativePreparation: Truerowwhile its pure-storage
Falserow passes.The rebuilt self-running xUnit executable was used, rather than treating a
successful build or zero-test invocation as execution:
Result with
MXC_E2E_PSEC_CAPABLE_HOST=1: 45 passed, none skipped or failed.The native-preparation gate was also exercised with these selectors:
With the opt-in unset, both pure-storage rows passed and the three native rows
skipped. With opt-in set to
1, all five passed. The scheduled result gateaccepted the enabled result and rejected the native skips.
Discovery selected all required native rows. Removing each required row
independently caused its discovery check to reject the listing.
Additional checks passed on unchanged FFI/code-generation inputs:
srccargo test -p mxc_ffi policy_preparationnode scripts\versioning\check-psec-codegen.jsNot run on this final candidate: the full scheduled host suite, a real governed
Windows refusal, Linux/macOS runtime suites, or a fresh Native AOT publication.
Governed-refusal CI provisioning remains separate agreed work; the host opt-in,
unit fixtures and preparation-success checks do not replace that coverage.
✅ Checklist
feature-acceptedCargo.lock, thedependency-feed-checkcheck passes (see pull request builds)The final two conditional items do not apply: no new build/architecture
conventions and no
Cargo.lockchanges.📋 Issue Type
Microsoft Reviewers: Open in CodeFlow