feat(persist): default persistency path to systemd $STATE_DIRECTORY#191
Open
viktorbeck98 wants to merge 1 commit into
Open
feat(persist): default persistency path to systemd $STATE_DIRECTORY#191viktorbeck98 wants to merge 1 commit into
viktorbeck98 wants to merge 1 commit into
Conversation
PersistConfig.path defaulted to the CWD-relative "./state". Under systemd (CWD typically /), this resolves to /state — wrong location and needs root, and the save failure is swallowed as a warning, so state is silently lost. Default now reads systemd's $STATE_DIRECTORY (set by StateDirectory= in the unit file, which also creates the dir with correct ownership), taking the first entry of a colon-separated list, and falls back to ./state outside systemd. Explicit path= still overrides. Docs: systemd setup note + updated field table in docs/detectors.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
thorinaboenke
requested changes
Jun 30, 2026
| # Falls back to CWD-relative ./state outside systemd. Explicit path= wins. | ||
| path: str = Field( | ||
| default_factory=lambda: os.environ.get("STATE_DIRECTORY", "./state").split(":")[0] | ||
| ) |
Contributor
There was a problem hiding this comment.
what happens when STATE_DIRECTORY="", or if it starts with a colon? overwrites the path with an empty string, then the complete path will become /MyDetector and also have permission errors (root)
| # unit file) so services persist to /var/lib/<dir> with no explicit path=. | ||
| # Falls back to CWD-relative ./state outside systemd. Explicit path= wins. | ||
| path: str = Field( | ||
| default_factory=lambda: os.environ.get("STATE_DIRECTORY", "./state").split(":")[0] |
Contributor
There was a problem hiding this comment.
Suggested change
| default_factory=lambda: os.environ.get("STATE_DIRECTORY", "./state").split(":")[0] | |
| default_factory=lambda: (os.environ.get("STATE_DIRECTORY") or "./state").split(":")[0] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Task
#190
Description
PersistConfig.pathdefaulted to the CWD-relative"./state". Under systemd(where the service CWD is typically
/unlessWorkingDirectory=is set), thisresolves to
/state— the wrong location, and writable only by root. Worse, theresulting save failure is swallowed as a
logger.warninginPersistencySaver.save(),so the detector keeps running and silently persists nothing.
This PR makes the default environment-aware:
PersistConfig.pathnow defaults to systemd's$STATE_DIRECTORY(set byStateDirectory=in the unit file, which also creates the directory with thecorrect service-user ownership), falling back to
./stateoutside systemd.$STATE_DIRECTORY(systemd's format for multipleStateDirectory=entries) uses the first path.PersistConfig(path=...)still wins —default_factoryonly runswhen
pathis omitted, so no existing caller changes.Implemented as a one-line
Field(default_factory=...); no hardcoded system path,which keeps the library portable across containers, non-root, and dev.
Docs (
docs/detectors.md): added a "Running under systemd" note with a unit-fileexample and updated the
pathfield table.Out of scope (worth separate issues): an
XDG_STATE_HOMEfallback fornon-systemd user daemons, and making
PersistencySaver.save()fail fast / escalateinstead of silently swallowing permanent save failures.
How Has This Been Tested?
Added unit tests in
detectmatelibrary_tests/test_common/test_persist_config.py(class
TestPersistConfigStateDirectoryDefault), written test-first:$STATE_DIRECTORYwhen set,./statewhen unset,path=overrides the env var.Also pinned
$STATE_DIRECTORYunset in the existingtest_defaults(the changemade it env-sensitive).
uv run pytestgreen: 19 passing in the persist-configsuite, 143 across the persistency-related suites.
prekhooks (mypy, flake8,bandit, …) all pass.
Checklist