diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index de32ea0..7eb88cb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -78,7 +78,7 @@ jobs:
uses: actions/checkout@v6
- name: Rust cache
- uses: Swatinem/rust-cache@v2.7.3
+ uses: Swatinem/rust-cache@v2.9.1
- name: Binary cache
uses: actions/cache@v5
diff --git a/policies/dotnet/Devolutions.Now.Policy.Api/Enums.cs b/policies/dotnet/Devolutions.Now.Policy.Api/Enums.cs
index 9efba8a..8e13592 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Api/Enums.cs
+++ b/policies/dotnet/Devolutions.Now.Policy.Api/Enums.cs
@@ -21,6 +21,20 @@ public enum ManagerName
Winget,
PowerShell,
PowerShell7,
+ Apt,
+ Bun,
+ Cargo,
+ Chocolatey,
+ Dnf,
+ Dotnet,
+ Flatpak,
+ Homebrew,
+ Npm,
+ Pacman,
+ Pip,
+ Scoop,
+ Snap,
+ Vcpkg,
}
/// Installation scope.
diff --git a/policies/dotnet/Devolutions.Now.Policy.Api/MetaModels.cs b/policies/dotnet/Devolutions.Now.Policy.Api/MetaModels.cs
index 7c9d03e..871ea38 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Api/MetaModels.cs
+++ b/policies/dotnet/Devolutions.Now.Policy.Api/MetaModels.cs
@@ -58,6 +58,13 @@ public string ResponseKind
[JsonPropertyName("MaxRequestBodyBytes")]
public long MaxRequestBodyBytes { get; set; }
+
+ /// Capability entry advertised for , if any.
+ public ManagerCapability? GetManagerCapability(ManagerName manager)
+ => Managers.FirstOrDefault(capability => capability.Manager == manager);
+
+ /// Whether the broker advertises support for .
+ public bool SupportsManager(ManagerName manager) => GetManagerCapability(manager) is not null;
}
public sealed class ManagerCapability
diff --git a/policies/dotnet/Devolutions.Now.Policy.Api/PolicyCompatibility.cs b/policies/dotnet/Devolutions.Now.Policy.Api/PolicyCompatibility.cs
index c102ff8..c1b402f 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Api/PolicyCompatibility.cs
+++ b/policies/dotnet/Devolutions.Now.Policy.Api/PolicyCompatibility.cs
@@ -31,6 +31,20 @@ public static class PolicyCompatibility
ManagerName.Winget => PolicyManagerName.Winget,
ManagerName.PowerShell => PolicyManagerName.PowerShell,
ManagerName.PowerShell7 => PolicyManagerName.PowerShell7,
+ ManagerName.Apt => PolicyManagerName.Apt,
+ ManagerName.Bun => PolicyManagerName.Bun,
+ ManagerName.Cargo => PolicyManagerName.Cargo,
+ ManagerName.Chocolatey => PolicyManagerName.Chocolatey,
+ ManagerName.Dnf => PolicyManagerName.Dnf,
+ ManagerName.Dotnet => PolicyManagerName.Dotnet,
+ ManagerName.Flatpak => PolicyManagerName.Flatpak,
+ ManagerName.Homebrew => PolicyManagerName.Homebrew,
+ ManagerName.Npm => PolicyManagerName.Npm,
+ ManagerName.Pacman => PolicyManagerName.Pacman,
+ ManagerName.Pip => PolicyManagerName.Pip,
+ ManagerName.Scoop => PolicyManagerName.Scoop,
+ ManagerName.Snap => PolicyManagerName.Snap,
+ ManagerName.Vcpkg => PolicyManagerName.Vcpkg,
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null),
};
@@ -39,6 +53,20 @@ public static class PolicyCompatibility
PolicyManagerName.Winget => ManagerName.Winget,
PolicyManagerName.PowerShell => ManagerName.PowerShell,
PolicyManagerName.PowerShell7 => ManagerName.PowerShell7,
+ PolicyManagerName.Apt => ManagerName.Apt,
+ PolicyManagerName.Bun => ManagerName.Bun,
+ PolicyManagerName.Cargo => ManagerName.Cargo,
+ PolicyManagerName.Chocolatey => ManagerName.Chocolatey,
+ PolicyManagerName.Dnf => ManagerName.Dnf,
+ PolicyManagerName.Dotnet => ManagerName.Dotnet,
+ PolicyManagerName.Flatpak => ManagerName.Flatpak,
+ PolicyManagerName.Homebrew => ManagerName.Homebrew,
+ PolicyManagerName.Npm => ManagerName.Npm,
+ PolicyManagerName.Pacman => ManagerName.Pacman,
+ PolicyManagerName.Pip => ManagerName.Pip,
+ PolicyManagerName.Scoop => ManagerName.Scoop,
+ PolicyManagerName.Snap => ManagerName.Snap,
+ PolicyManagerName.Vcpkg => ManagerName.Vcpkg,
_ => throw new ArgumentOutOfRangeException(nameof(value), value, null),
};
diff --git a/policies/dotnet/Devolutions.Now.Policy.Client.Tests/BrokerClientTests.cs b/policies/dotnet/Devolutions.Now.Policy.Client.Tests/BrokerClientTests.cs
index 698c165..4c360ab 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Client.Tests/BrokerClientTests.cs
+++ b/policies/dotnet/Devolutions.Now.Policy.Client.Tests/BrokerClientTests.cs
@@ -170,6 +170,27 @@ public async Task Evaluate_rejects_unsupported_capability_before_operation_reque
Assert.Equal("/v1/capabilities", transport.Requests[0].Path);
}
+ [Fact]
+ public async Task Evaluate_rejects_manager_not_advertised_by_broker_before_sending()
+ {
+ // The broker does not advertise Chocolatey in its capabilities.
+ var transport = new FakeBrokerTransport(CapabilitiesResponse);
+ var client = CreateClient(transport);
+
+ var exception = await Assert.ThrowsAsync(() => client.Evaluate(new PackageOperationRequest
+ {
+ Operation = Operation.Install,
+ Manager = ManagerName.Chocolatey,
+ Source = new RequestSource { Name = "chocolatey" },
+ Package = new RequestPackage { Id = "git" },
+ }));
+
+ Assert.Equal(BrokerClientErrorKind.UnsupportedCapability, exception.Kind);
+ Assert.Contains("does not advertise support", exception.Message);
+ Assert.Single(transport.Requests);
+ Assert.Equal("/v1/capabilities", transport.Requests[0].Path);
+ }
+
[Fact]
public async Task GetHealth_throws_typed_error_for_broker_error_response()
{
diff --git a/policies/dotnet/Devolutions.Now.Policy.Client/README.md b/policies/dotnet/Devolutions.Now.Policy.Client/README.md
index 716dea7..65c54af 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Client/README.md
+++ b/policies/dotnet/Devolutions.Now.Policy.Client/README.md
@@ -62,7 +62,7 @@ discriminators automatically while the client fills `RequestVersion` at the top
and `ResponseVersion`; this is required for further protocol evolution and allows the client to
switch transport from HTTP to other mechanisms without changing the wire schema.
-Before sending package operation and status requests, the client implicitly queries `GetCapabilities` once and caches the result. The cached capabilities are used as a local preflight gate: unsupported transports, package managers, operations, scopes, architectures, request body sizes, custom parameters, custom install locations, or captured output requests fail before the client sends the operation/status request.
+Before sending package operation and status requests, the client implicitly queries `GetCapabilities` once and caches the result. The cached capabilities are used as a local preflight gate: unsupported transports, package managers, operations, scopes, architectures, request body sizes, custom parameters, custom install locations, or captured output requests fail before the client sends the operation/status request. Use `CapabilitiesResponse.SupportsManager(ManagerName)` or `GetManagerCapability(ManagerName)` to check package manager support ahead of time.
Before sending package operation requests, the client fills missing request metadata:
diff --git a/policies/dotnet/Devolutions.Now.Policy.Model/Enums.cs b/policies/dotnet/Devolutions.Now.Policy.Model/Enums.cs
index f1a1fe3..aa93641 100644
--- a/policies/dotnet/Devolutions.Now.Policy.Model/Enums.cs
+++ b/policies/dotnet/Devolutions.Now.Policy.Model/Enums.cs
@@ -18,6 +18,20 @@ public enum ManagerName
Winget,
PowerShell,
PowerShell7,
+ Apt,
+ Bun,
+ Cargo,
+ Chocolatey,
+ Dnf,
+ Dotnet,
+ Flatpak,
+ Homebrew,
+ Npm,
+ Pacman,
+ Pip,
+ Scoop,
+ Snap,
+ Vcpkg,
}
/// Installation scope.
diff --git a/policies/rust/now-policy-api/openapi/now-policy-api.yaml b/policies/rust/now-policy-api/openapi/now-policy-api.yaml
index 223f94a..f057d30 100644
--- a/policies/rust/now-policy-api/openapi/now-policy-api.yaml
+++ b/policies/rust/now-policy-api/openapi/now-policy-api.yaml
@@ -543,6 +543,20 @@ components:
- Winget
- PowerShell
- PowerShell7
+ - Apt
+ - Bun
+ - Cargo
+ - Chocolatey
+ - Dnf
+ - Dotnet
+ - Flatpak
+ - Homebrew
+ - Npm
+ - Pacman
+ - Pip
+ - Scoop
+ - Snap
+ - Vcpkg
Operation:
description: Package operation type.
type: string
diff --git a/policies/rust/now-policy-api/src/capabilities.rs b/policies/rust/now-policy-api/src/capabilities.rs
index 4377372..1984941 100644
--- a/policies/rust/now-policy-api/src/capabilities.rs
+++ b/policies/rust/now-policy-api/src/capabilities.rs
@@ -31,6 +31,18 @@ pub struct CapabilitiesResponse {
pub max_request_body_bytes: u64,
}
+impl CapabilitiesResponse {
+ /// Capability entry advertised for `manager`, if any.
+ pub fn manager_capability(&self, manager: ManagerName) -> Option<&ManagerCapability> {
+ self.managers.iter().find(|capability| capability.manager == manager)
+ }
+
+ /// Whether the broker advertises support for `manager`.
+ pub fn supports_manager(&self, manager: ManagerName) -> bool {
+ self.manager_capability(manager).is_some()
+ }
+}
+
/// Package-manager-specific capability declaration.
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[schemars(rename = "ManagerCapability")]
@@ -64,3 +76,59 @@ pub struct ManagerCapability {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_operation_timeout_seconds: Option,
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::{API_VERSION_STR, ServerContext, Transport};
+
+ fn capabilities(response_version: &str, managers: Vec) -> CapabilitiesResponse {
+ CapabilitiesResponse {
+ response_kind: CapabilitiesResponseKind,
+ response_version: response_version.into(),
+ server: ServerContext {
+ server_version: "0.1.0".to_owned(),
+ transport: Transport::HttpNamedPipe,
+ },
+ transports: vec![Transport::HttpNamedPipe],
+ managers,
+ max_request_body_bytes: 262144,
+ }
+ }
+
+ fn manager_capability(manager: ManagerName) -> ManagerCapability {
+ ManagerCapability {
+ manager,
+ operations: vec![Operation::Install],
+ scopes: vec![Scope::Machine],
+ architectures: vec![Architecture::Neutral],
+ supports_custom_parameters: false,
+ supports_custom_install_location: false,
+ supports_capture_output: false,
+ supports_details: false,
+ max_operation_timeout_seconds: None,
+ }
+ }
+
+ #[test]
+ fn supports_manager_reflects_advertised_capabilities() {
+ let broker = capabilities(
+ API_VERSION_STR,
+ vec![
+ manager_capability(ManagerName::Winget),
+ manager_capability(ManagerName::Chocolatey),
+ ],
+ );
+
+ assert!(broker.supports_manager(ManagerName::Winget));
+ assert!(broker.supports_manager(ManagerName::Chocolatey));
+ assert!(!broker.supports_manager(ManagerName::Scoop));
+ assert!(broker.manager_capability(ManagerName::Scoop).is_none());
+ assert_eq!(
+ broker
+ .manager_capability(ManagerName::Chocolatey)
+ .map(|capability| capability.manager),
+ Some(ManagerName::Chocolatey)
+ );
+ }
+}
diff --git a/policies/rust/now-policy-api/src/enums.rs b/policies/rust/now-policy-api/src/enums.rs
index a7ea0db..7b3413c 100644
--- a/policies/rust/now-policy-api/src/enums.rs
+++ b/policies/rust/now-policy-api/src/enums.rs
@@ -37,6 +37,20 @@ pub enum ManagerName {
Winget,
PowerShell,
PowerShell7,
+ Apt,
+ Bun,
+ Cargo,
+ Chocolatey,
+ Dnf,
+ Dotnet,
+ Flatpak,
+ Homebrew,
+ Npm,
+ Pacman,
+ Pip,
+ Scoop,
+ Snap,
+ Vcpkg,
}
/// Policy decision.
diff --git a/policies/rust/now-policy-api/src/policy_compat.rs b/policies/rust/now-policy-api/src/policy_compat.rs
index b8406a2..33d17d1 100644
--- a/policies/rust/now-policy-api/src/policy_compat.rs
+++ b/policies/rust/now-policy-api/src/policy_compat.rs
@@ -44,7 +44,29 @@ macro_rules! bidirectional_newtype_conversion {
bidirectional_enum_conversion!(Operation, now_policy::Operation, [Install, Update, Uninstall]);
bidirectional_enum_conversion!(Scope, now_policy::Scope, [User, Machine]);
bidirectional_enum_conversion!(Architecture, now_policy::Architecture, [X86, X64, Arm64, Neutral]);
-bidirectional_enum_conversion!(ManagerName, now_policy::ManagerName, [Winget, PowerShell, PowerShell7]);
+bidirectional_enum_conversion!(
+ ManagerName,
+ now_policy::ManagerName,
+ [
+ Winget,
+ PowerShell,
+ PowerShell7,
+ Apt,
+ Bun,
+ Cargo,
+ Chocolatey,
+ Dnf,
+ Dotnet,
+ Flatpak,
+ Homebrew,
+ Npm,
+ Pacman,
+ Pip,
+ Scoop,
+ Snap,
+ Vcpkg,
+ ]
+);
bidirectional_enum_conversion!(Decision, now_policy::Decision, [Allow, Deny]);
bidirectional_enum_conversion!(Elevation, now_policy::Elevation, [Standard, Elevated]);
diff --git a/policies/rust/now-policy-server-template/assets/samples/requests/chocolatey-git-install.request.json b/policies/rust/now-policy-server-template/assets/samples/requests/chocolatey-git-install.request.json
new file mode 100644
index 0000000..4a287ec
--- /dev/null
+++ b/policies/rust/now-policy-server-template/assets/samples/requests/chocolatey-git-install.request.json
@@ -0,0 +1,32 @@
+{
+ "RequestKind": "PackageRequest",
+ "RequestVersion": "1.0",
+ "RequestId": "req-chocolatey-git-install",
+ "CreatedAt": "2026-05-05T12:00:00Z",
+ "Operation": "Install",
+ "Manager": "Chocolatey",
+ "Source": {
+ "Name": "chocolatey",
+ "Url": "https://community.chocolatey.org/api/v2/"
+ },
+ "Package": {
+ "Id": "git",
+ "Architecture": "X64"
+ },
+ "Options": {
+ "Scope": "Machine",
+ "Interactive": false,
+ "SkipHashCheck": false,
+ "PreRelease": false,
+ "CustomParameters": [],
+ "KillBeforeOperation": []
+ },
+ "Client": {
+ "RequestedElevation": "Elevated",
+ "EffectiveUser": "CONTOSO\\alice",
+ "ClientVersion": "3.2.0",
+ "Transport": "HttpNamedPipe",
+ "ClientExecutablePath": "C:\\Program Files\\Devolutions\\NOW\\now-client.exe"
+ },
+ "IncludeCommandPreview": true
+}
diff --git a/policies/rust/now-policy-server-template/assets/samples/responses/capabilities.response.json b/policies/rust/now-policy-server-template/assets/samples/responses/capabilities.response.json
index 0744c95..e854714 100644
--- a/policies/rust/now-policy-server-template/assets/samples/responses/capabilities.response.json
+++ b/policies/rust/now-policy-server-template/assets/samples/responses/capabilities.response.json
@@ -29,8 +29,8 @@
"SupportsCustomParameters": true,
"SupportsCustomInstallLocation": true,
"SupportsCaptureOutput": true,
- "MaxOperationTimeoutSeconds": 1800,
- "SupportsDetails": true
+ "SupportsDetails": true,
+ "MaxOperationTimeoutSeconds": 1800
},
{
"Manager": "PowerShell",
@@ -49,8 +49,8 @@
"SupportsCustomParameters": true,
"SupportsCustomInstallLocation": false,
"SupportsCaptureOutput": true,
- "MaxOperationTimeoutSeconds": 1800,
- "SupportsDetails": false
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
},
{
"Manager": "PowerShell7",
@@ -69,8 +69,285 @@
"SupportsCustomParameters": true,
"SupportsCustomInstallLocation": false,
"SupportsCaptureOutput": true,
- "MaxOperationTimeoutSeconds": 1800,
- "SupportsDetails": false
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Apt",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Bun",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Cargo",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Chocolatey",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "Machine"
+ ],
+ "Architectures": [
+ "X86",
+ "X64",
+ "Arm64",
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": true,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Dnf",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Dotnet",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User",
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": true,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Flatpak",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User",
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Homebrew",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Npm",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User",
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Pacman",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Pip",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User",
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Scoop",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User",
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Snap",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "Machine"
+ ],
+ "Architectures": [
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
+ },
+ {
+ "Manager": "Vcpkg",
+ "Operations": [
+ "Install",
+ "Update",
+ "Uninstall"
+ ],
+ "Scopes": [
+ "User"
+ ],
+ "Architectures": [
+ "X86",
+ "X64",
+ "Arm64",
+ "Neutral"
+ ],
+ "SupportsCustomParameters": true,
+ "SupportsCustomInstallLocation": false,
+ "SupportsCaptureOutput": true,
+ "SupportsDetails": false,
+ "MaxOperationTimeoutSeconds": 1800
}
],
"MaxRequestBodyBytes": 262144
diff --git a/policies/rust/now-policy-server-template/src/mock.rs b/policies/rust/now-policy-server-template/src/mock.rs
index a20ddd5..4285057 100644
--- a/policies/rust/now-policy-server-template/src/mock.rs
+++ b/policies/rust/now-policy-server-template/src/mock.rs
@@ -120,44 +120,148 @@ fn server_context() -> ServerContext {
}
fn default_manager_capabilities() -> Vec {
- vec![
- ManagerCapability {
- manager: ManagerName::Winget,
- operations: vec![Operation::Install, Operation::Update, Operation::Uninstall],
- scopes: vec![Scope::User, Scope::Machine],
- architectures: vec![
- Architecture::X86,
- Architecture::X64,
- Architecture::Arm64,
- Architecture::Neutral,
- ],
- supports_custom_parameters: true,
- supports_custom_install_location: true,
- supports_capture_output: true,
- supports_details: true,
- max_operation_timeout_seconds: Some(1800),
- },
- ManagerCapability {
- manager: ManagerName::PowerShell,
- operations: vec![Operation::Install, Operation::Update, Operation::Uninstall],
- scopes: vec![Scope::User, Scope::Machine],
- architectures: vec![Architecture::Neutral],
- supports_custom_parameters: true,
- supports_custom_install_location: false,
- supports_capture_output: true,
- supports_details: false,
- max_operation_timeout_seconds: Some(1800),
- },
+ fn manager(
+ manager: ManagerName,
+ scopes: Vec,
+ architectures: Vec,
+ supports_custom_install_location: bool,
+ supports_details: bool,
+ ) -> ManagerCapability {
ManagerCapability {
- manager: ManagerName::PowerShell7,
+ manager,
operations: vec![Operation::Install, Operation::Update, Operation::Uninstall],
- scopes: vec![Scope::User, Scope::Machine],
- architectures: vec![Architecture::Neutral],
+ scopes,
+ architectures,
supports_custom_parameters: true,
- supports_custom_install_location: false,
+ supports_custom_install_location,
supports_capture_output: true,
- supports_details: false,
+ supports_details,
max_operation_timeout_seconds: Some(1800),
- },
+ }
+ }
+
+ let all_architectures = || {
+ vec![
+ Architecture::X86,
+ Architecture::X64,
+ Architecture::Arm64,
+ Architecture::Neutral,
+ ]
+ };
+
+ vec![
+ manager(
+ ManagerName::Winget,
+ vec![Scope::User, Scope::Machine],
+ all_architectures(),
+ true,
+ true,
+ ),
+ manager(
+ ManagerName::PowerShell,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::PowerShell7,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Apt,
+ vec![Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Bun,
+ vec![Scope::User],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Cargo,
+ vec![Scope::User],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Chocolatey,
+ vec![Scope::Machine],
+ all_architectures(),
+ true,
+ false,
+ ),
+ manager(
+ ManagerName::Dnf,
+ vec![Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Dotnet,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ true,
+ false,
+ ),
+ manager(
+ ManagerName::Flatpak,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Homebrew,
+ vec![Scope::User],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Npm,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Pacman,
+ vec![Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Pip,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Scoop,
+ vec![Scope::User, Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(
+ ManagerName::Snap,
+ vec![Scope::Machine],
+ vec![Architecture::Neutral],
+ false,
+ false,
+ ),
+ manager(ManagerName::Vcpkg, vec![Scope::User], all_architectures(), false, false),
]
}
diff --git a/policies/rust/now-policy/schema/devolutions.now-policy.schema.json b/policies/rust/now-policy/schema/devolutions.now-policy.schema.json
index cc059bf..c983aa9 100644
--- a/policies/rust/now-policy/schema/devolutions.now-policy.schema.json
+++ b/policies/rust/now-policy/schema/devolutions.now-policy.schema.json
@@ -46,7 +46,21 @@
"enum": [
"Winget",
"PowerShell",
- "PowerShell7"
+ "PowerShell7",
+ "Apt",
+ "Bun",
+ "Cargo",
+ "Chocolatey",
+ "Dnf",
+ "Dotnet",
+ "Flatpak",
+ "Homebrew",
+ "Npm",
+ "Pacman",
+ "Pip",
+ "Scoop",
+ "Snap",
+ "Vcpkg"
],
"type": "string"
},
diff --git a/policies/rust/now-policy/src/enums.rs b/policies/rust/now-policy/src/enums.rs
index f363a03..35c926a 100644
--- a/policies/rust/now-policy/src/enums.rs
+++ b/policies/rust/now-policy/src/enums.rs
@@ -37,6 +37,20 @@ pub enum ManagerName {
Winget,
PowerShell,
PowerShell7,
+ Apt,
+ Bun,
+ Cargo,
+ Chocolatey,
+ Dnf,
+ Dotnet,
+ Flatpak,
+ Homebrew,
+ Npm,
+ Pacman,
+ Pip,
+ Scoop,
+ Snap,
+ Vcpkg,
}
/// Policy decision.
@@ -80,6 +94,20 @@ impl std::fmt::Display for ManagerName {
Self::Winget => f.write_str("Winget"),
Self::PowerShell => f.write_str("PowerShell"),
Self::PowerShell7 => f.write_str("PowerShell7"),
+ Self::Apt => f.write_str("Apt"),
+ Self::Bun => f.write_str("Bun"),
+ Self::Cargo => f.write_str("Cargo"),
+ Self::Chocolatey => f.write_str("Chocolatey"),
+ Self::Dnf => f.write_str("Dnf"),
+ Self::Dotnet => f.write_str("Dotnet"),
+ Self::Flatpak => f.write_str("Flatpak"),
+ Self::Homebrew => f.write_str("Homebrew"),
+ Self::Npm => f.write_str("Npm"),
+ Self::Pacman => f.write_str("Pacman"),
+ Self::Pip => f.write_str("Pip"),
+ Self::Scoop => f.write_str("Scoop"),
+ Self::Snap => f.write_str("Snap"),
+ Self::Vcpkg => f.write_str("Vcpkg"),
}
}
}