feat: consolidate proxy config into structured section and add support for custom commands to skip proxy (#240)

* feat: add ProxyConfig struct with per-PM skip_commands and legacy fallback

* feat: consolidate proxy config into structured section with backward compat

Replaces flat proxy_mode/proxy_install_only keys with a structured proxy
section supporting per-package-manager skip_commands. Legacy keys are
respected via fallback when user's config lacks the new proxy section.
Removes deprecated experimental_proxy_mode config and flag.

* fix: env var resolution for nested config keys and deduplicate skip command matching

- Add "." to "_" in Viper env key replacer so nested keys like
  sandbox.enabled resolve from PMG_SANDBOX_ENABLED (was silently broken)
- Export IsFirstNonFlagArgInList and remove duplicate from proxy_flow.go
- Add table-driven tests for skip command matching with real-world cases
- Remove redundant env var test

* docs: update proxy configuration and env var documentation

Update config.md env var table to reflect new proxy.enabled and
proxy.install_only keys. Add proxy configuration section to proxy.md
covering config structure, per-PM skip commands, CLI flags, and env vars.

* fix: legacy fallback precedence
This commit is contained in:
Sahil Bansal
2026-05-06 18:27:23 +05:30
committed by GitHub
parent d6755d3f44
commit d1dd2560a4
15 changed files with 423 additions and 71 deletions
+20 -13
View File
@@ -65,17 +65,10 @@ type Config struct {
// EventLogRetentionDays is the number of days to retain event logs.
EventLogRetentionDays int `mapstructure:"event_log_retention_days"`
// ProxyMode enables proxy-based package interception when supported by package managers.
// When enabled, PMG starts a proxy server and intercepts package manager requests in real-time.
// Deprecated: Use Proxy.Enabled instead. Kept for backward compatibility with old config files.
ProxyMode bool `mapstructure:"proxy_mode"`
// ExperimentalProxyMode is same as ProxyMode. Kept here for backward compatibility because
// we initially introduced it as an experimental feature.
ExperimentalProxyMode bool `mapstructure:"experimental_proxy_mode"`
// ProxyInstallOnly restricts proxy interception to install commands only.
// When false (default), proxy runs for all package manager commands.
// When true, non-install commands (e.g., npm ls, pip list) bypass the proxy and execute directly.
// Deprecated: Use Proxy.InstallOnly instead. Kept for backward compatibility with old config files.
ProxyInstallOnly bool `mapstructure:"proxy_install_only"`
// Verbosity controls the UI verbosity level. Valid values: "silent", "normal", "verbose".
@@ -88,6 +81,8 @@ type Config struct {
DependencyCooldown DependencyCooldownConfig `mapstructure:"dependency_cooldown"`
Cloud CloudConfig `mapstructure:"cloud"`
Proxy ProxyConfig `mapstructure:"proxy"`
}
// CloudConfig configures audit event sync to SafeDep Cloud.
@@ -96,6 +91,16 @@ type CloudConfig struct {
EndpointID string `mapstructure:"endpoint_id"`
}
type ProxyPolicy struct {
SkipCommands []string `mapstructure:"skip_commands"`
}
type ProxyConfig struct {
Enabled bool `mapstructure:"enabled"`
InstallOnly bool `mapstructure:"install_only"`
Policies map[string]ProxyPolicy `mapstructure:"policies"`
}
// SandboxConfig configures the sandbox system for isolating package manager processes.
type SandboxConfig struct {
// Enabled enables sandbox mode (opt-in by default for backward compatibility).
@@ -199,10 +204,8 @@ func (r *RuntimeConfig) ConfigDir() string {
return r.configDir
}
// IsProxyModeEnabled is a helper function to check for proxy mode with
// support for backward compatibility
func (r *RuntimeConfig) IsProxyModeEnabled() bool {
return (r.Config.ExperimentalProxyMode || r.Config.ProxyMode)
return r.Config.Proxy.Enabled
}
// SandboxAllowType represents the type of a sandbox allow override.
@@ -248,7 +251,6 @@ func DefaultConfig() RuntimeConfig {
DisableTelemetry: false,
EventLogRetentionDays: 7,
SkipEventLogging: false,
ExperimentalProxyMode: false,
TrustedPackages: []TrustedPackage{},
ProxyMode: true,
Verbosity: VerbosityNormal,
@@ -263,6 +265,11 @@ func DefaultConfig() RuntimeConfig {
Cloud: CloudConfig{
Enabled: false,
},
Proxy: ProxyConfig{
Enabled: true,
InstallOnly: false,
Policies: map[string]ProxyPolicy{},
},
},
DryRun: false,
InsecureInstallation: insecureInstallation,