Describe the bug
_get_policy_scripts_dir() hardcodes the C: drive for the admin policy tier:
# src/apm_cli/core/lifecycle_scripts.py:346-351
def _get_policy_scripts_dir() -> Path:
"""Return the platform-specific policy scripts directory."""
system = platform.system()
if system == "Windows":
return Path(r"C:\ProgramData\APM\policy.d")
return Path("/etc/apm/policy.d")
Windows does not define ProgramData as a constant. It is stored in the registry as an
unexpanded string and expanded at runtime:
> (Get-Item 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList').GetValue(
'ProgramData', $null, 'DoNotExpandEnvironmentNames')
%SystemDrive%\ProgramData
So on a machine whose %SystemDrive% is not C:, apm reads the admin tier from a
directory that is not that machine's ProgramData. The failure is silent:
_load_scripts_from_dir() returns [] for a missing directory (line 373), with no
warning. Admin-tier lifecycle policy contributes zero scripts and the tier documented as
the trust anchor quietly does nothing.
The user tier in the same module already resolves from the environment
(_get_user_apm_yml() honours APM_HOME), so the two tiers disagree about whether
location is configurable.
Expected behavior
Resolve the directory from the environment rather than a literal, e.g.
Path(os.environ.get("ProgramData", r"C:\ProgramData")) / "APM" / "policy.d".
To Reproduce
I could not reproduce end-user impact here: this machine's %SystemDrive% is C:, so the
hardcoded path happens to be correct. What I did verify by running it is that the function
ignores the environment entirely, while the user tier beside it does not:
import os
from apm_cli.core import lifecycle_scripts as ls
print(ls._get_policy_scripts_dir()) # C:\ProgramData\APM\policy.d
os.environ["ProgramData"] = r"D:\ProgramData"
print(ls._get_policy_scripts_dir()) # C:\ProgramData\APM\policy.d <- unchanged
os.environ["APM_HOME"] = r"D:\apm-home"
print(ls._get_user_apm_yml()) # D:\apm-home\apm.yml <- follows env
Environment
- OS: Windows 11 Home
- Python Version: 3.13.13
- APM Version: 0.28.0 (
lifecycle_scripts.py byte-identical to main @ 88cf78a)
Additional context
No test references ProgramData, so the literal does not read as a deliberately pinned
choice. One judgement call belongs to you rather than to me: on a non-C: system that
already has scripts in C:\ProgramData\APM\policy.d, switching to the environment would
stop reading them. That is why this is an issue and not a patch.
Written with AI assistance. On this machine I ran the probe above and the registry query,
and read _get_policy_scripts_dir and _load_scripts_from_dir in full; I have not tested
on an install whose SystemDrive is not C:, and have not claimed otherwise above.
Describe the bug
_get_policy_scripts_dir()hardcodes theC:drive for the admin policy tier:Windows does not define ProgramData as a constant. It is stored in the registry as an
unexpanded string and expanded at runtime:
So on a machine whose
%SystemDrive%is notC:, apm reads the admin tier from adirectory that is not that machine's ProgramData. The failure is silent:
_load_scripts_from_dir()returns[]for a missing directory (line 373), with nowarning. Admin-tier lifecycle policy contributes zero scripts and the tier documented as
the trust anchor quietly does nothing.
The user tier in the same module already resolves from the environment
(
_get_user_apm_yml()honoursAPM_HOME), so the two tiers disagree about whetherlocation is configurable.
Expected behavior
Resolve the directory from the environment rather than a literal, e.g.
Path(os.environ.get("ProgramData", r"C:\ProgramData")) / "APM" / "policy.d".To Reproduce
I could not reproduce end-user impact here: this machine's
%SystemDrive%isC:, so thehardcoded path happens to be correct. What I did verify by running it is that the function
ignores the environment entirely, while the user tier beside it does not:
Environment
lifecycle_scripts.pybyte-identical tomain@88cf78a)Additional context
No test references ProgramData, so the literal does not read as a deliberately pinned
choice. One judgement call belongs to you rather than to me: on a non-
C:system thatalready has scripts in
C:\ProgramData\APM\policy.d, switching to the environment wouldstop reading them. That is why this is an issue and not a patch.
Written with AI assistance. On this machine I ran the probe above and the registry query,
and read
_get_policy_scripts_dirand_load_scripts_from_dirin full; I have not testedon an install whose SystemDrive is not
C:, and have not claimed otherwise above.