# PMG configuration template. Customize this file as needed.
# https://github.com/safedep/pmg

# Enable transitive dependency resolution. Default is true.
transitive: true

# Maximum depth of transitive dependencies to resolve. Default is 5.
transitive_depth: 5

# Include dev dependencies in the dependency graph. Default is false.
include_dev_dependencies: false

# UI verbosity level. Valid values: silent, normal, verbose. Default is normal.
# silent: PMG is hidden from the user except for errors and malicious package detection
# normal: Show minimal status updates
# verbose: Show verbose status updates and detailed information
verbosity: normal

# Enable paranoid mode. In paranoid mode, PMG will treat suspicious packages
# as malicious packages
paranoid: false

# Disable anonymous telemetry. Default is false.
disable_telemetry: false

# Skip event logging. Default is false.
# When skip_event_logging is false, all events will be logged to file. These events are useful for audit
# trail and incident response on systems using PMG. Set this config to true to disable event logging.
skip_event_logging: false

# Event log retention days. Default is 7.
# This is the number of days to retain event logs.
event_log_retention_days: 7

# Proxy configuration.
# When enabled, PMG uses a proxy-based interception approach instead of the
# default guard-based analysis. The proxy intercepts package manager requests in real-time
# and analyzes packages as they are downloaded. Proxy mode may not work in all environments,
# and can be disabled to fall back to the guard-based analysis.
proxy:
  enabled: true

  # When true, only install commands are proxied. Other commands
  # (e.g., npm ls, pip list) bypass the proxy and execute directly.
  install_only: false

  # Per-package-manager commands to skip proxying (only applies when install_only is true).
  # Example:
  #   skip_commands:
  #     pip: ["list", "show"]
  skip_commands:
    npm: []

# Trusted packages are packages that are trusted by the user and will be ignored by the security guardrails.
# This is useful for packages that are known to be safe and are used in the application.
# Example:
#   - purl: pkg:npm/@safedep/pmg
#     reason: "PMG is a trusted package for PMG"
#
# When a package is specified without an explicit version, all versions of the package will be trusted.
# This feature should be used with caution and should be used for minimal set of packages.
#
# When a package is specified with an explicit version, only that version will be trusted.
#
# The purl is the package identifier and the reason is the reason for trusting the package.
# PURL specification: https://github.com/package-url/purl-spec
trusted_packages:
  - purl: pkg:npm/@safedep/pmg
    reason: "PMG is a trusted package for PMG"

# Sandbox configuration (EXPERIMENTAL)
# When enabled, package managers run in sandbox environments with restricted
# filesystem, network, and process execution access. This provides defense-in-depth
# protection against malicious install scripts and supply chain attacks.
#
# When sandboxing is enabled for a package manager, policy violations will block execution
# (no "warn-only" mode). Sandboxing itself can be disabled globally or per package manager.
#
# Currently supported platforms:
# - macOS (using Seatbelt sandbox-exec)
# - Linux (using Bubblewrap with namespace isolation)
# - Windows (planned)
#
# Platform-specific limitations:
# - Linux: Filesystem permissions use coarse-grained bind mounts. Glob patterns (e.g., *.txt)
#   are expanded at policy translation time, but entire directories may be mounted rather than
#   individual matching files. This is less precise than macOS regex-based filtering.
# - macOS: Network filtering is limited (all-or-nothing for most policies).
sandbox:
  # Enable sandbox mode (opt-in, default: false for backward compatibility)
  enabled: false

  # Controls scope of sandbox enforcement:
  # - true: sandbox applies to all package manager commands
  # - false (default): sandbox only applies to install commands, others run unrestricted
  # Requires 'enabled: true' and per-PM policies to be active. May break workflows expecting unrestricted commands.
  enforce_always: false

  # Policy templates define policy profiles by name and path.
  # They can be used to override a built-in profile or create a custom profile.
  # Note: Custom profiles loaded via policy_templates can inherit from built-in
  # profiles using the 'inherits' field in the YAML (e.g., inherits: npm-restrictive).
  # Inheritance allows you to extend a base profile with additional permissions.
  policy_templates:
    # Name for the template. Can be used to override a built-in profile or create a custom profile.
    # Path is the path to the template file.
    # Relative path can be used to reference a template file in the config directory (example: ./npm-restrictive.yml)
    npm-restrictive-override:
      path: ./profiles/npm-restrictive.yml

  # Per-package-manager sandbox policies
  # Each package manager can have its own policy to account for unique security characteristics
  policies:
    # npm ecosystem. npm-restrictive is the shared base profile; each package
    # manager maps to a leaf profile that re-allows only its own environment
    # variables.
    npm:
      enabled: true
      profile: npm # Built-in profile, template name, or path to custom YAML

    pnpm:
      enabled: true
      profile: pnpm

    npx:
      enabled: true
      profile: npx

    pnpx:
      enabled: true
      profile: npx

    yarn:
      enabled: true
      profile: yarn

    bun:
      enabled: true
      profile: bun

    # PyPI ecosystem. pypi-restrictive is the shared base profile; each
    # package manager maps to a leaf profile that re-allows only its own
    # environment variables.
    pip:
      enabled: true
      profile: pip

    pip3:
      enabled: true
      profile: pip

    pipx:
      enabled: true
      profile: pipx

    poetry:
      enabled: true
      profile: poetry

    uv:
      enabled: true
      profile: uv

# Dependency cooldown blocks installation of package versions published within
# a configurable time window.
dependency_cooldown:
  enabled: true
  days: 5

  # Per-control skip list of packages exempt from the cooldown window.
  # Packages here are STILL malware-scanned — only the cooldown wait is waived.
  # Use it for first-party / internal packages that must be installed immediately
  # on release (e.g. to sanity-test a freshly published version).
  #
  # To bypass every PMG control (malware analysis, cooldown, and any future
  # controls) for a package, add it to the top-level trusted_packages list
  # above instead. Trusted packages are automatically cooldown-exempt; you do
  # not need to repeat them here.
  #
  # A PURL without a version skips cooldown for ALL versions of the package; a
  # PURL with a version skips cooldown for that version only. Example:
  #   skip:
  #     - purl: pkg:npm/my-internal-sdk             # all versions
  #       reason: "First-party SDK; sanity-tested immediately on release"
  #     - purl: pkg:npm/another-internal-pkg@1.2.3  # only 1.2.3
  #       reason: "Pin a specific just-published build"
  skip: []

# Persistent analysis cache (opt-in). Caching is analyzer-specific, so config is
# nested per analyzer; today only the Malysis (malware) analyzer has a cache.
#
# By default PMG re-screens the whole resolved graph against the analysis
# backend on every install. When enabled, clean (ALLOW) verdicts are cached on
# disk and reused across runs, so repeat installs of an unchanged graph are
# fast. Only ALLOW verdicts are cached — suspicious, malicious, and
# tenant-excluded verdicts are always re-evaluated.
#
# Trade-off: a version that was clean when first screened but is later flagged
# malicious is served from cache until its entry expires; `ttl` bounds that
# window. Keep `ttl` short if you prefer freshness over speed.
analysis_cache:
  # Malysis is SafeDep's threat intelligence feed.
  # Set cache TTL to be lower than dependency cooldown period to have a compensating
  # control in place for newly published packages whose verdict is cached.
  malysis:
    enabled: false
    ttl: 24h

# Cloud sync configuration.
# When enabled, PMG audit events are synced to SafeDep Cloud for centralized visibility.
# Requires SAFEDEP_API_KEY and SAFEDEP_TENANT_ID environment variables for authentication.
cloud:
  enabled: false
  # Endpoint ID is not required. By default, it falls back to the machine's hostname.
  # Set it only if you want to explicitly override the identifier for this endpoint.
  endpoint_id: ""

  # Auto sync drains the local cloud-sync WAL to SafeDep Cloud opportunistically
  # at the end of each PMG invocation, gated by a per-host cooldown so it does
  # not fire on every command. The drain runs as a short-lived detached child
  # so the user-facing CLI returns immediately.
  #
  # Disable this in ephemeral environments (CI runners, throwaway VMs) where
  # the detached child may be torn down before it finishes draining; in those
  # environments, prefer an explicit `pmg cloud sync` at job-end.
  auto_sync:
    enabled: true

    # Minimum gap between sync attempts. The lastrun timestamp is updated on
    # every attempt (success or failure), so a failing cloud endpoint will not
    # cause every PMG invocation to retry. Reduce this if you want a more
    # aggressive retry cadence.
    min_interval: 15m

    # Hard timeout applied to a single background sync attempt.
    timeout: 5m
