- Merge all configuration into settings.py with PRY_* env var prefix.
- Add legacy env aliases (PROXY_URL, TOR_ENABLED, MAX_RETRIES, etc.) for migration.
- Load and persist runtime overrides from JSON config file (default /app/config.json).
- Update scraper.py, deps.py, routers/config.py to use unified settings.
- Add resolved_proxy_chain and resolved_proxy_url properties.
- Replace tests/test_mconfig.py with tests/test_settings.py (9 tests).
- Update .env.example with new PRY_* options.
- All 500 tests pass; ruff clean.
The SECURITY.md contract said "use gopass" but the code only used
os.getenv. The deploy at /srv/pry/ had an .env file with secrets in
it, which violates the SECURITY.md threat model.
New module secrets_backend.py provides:
get_secret(name, default) - resolves from gopass, env, or file
set_secret(name, value) - writes to gopass
backend_info() - diagnostic dict for /health or /status
Backends selected by PRY_SECRET_BACKEND env var:
gopass (default) - reads from gopass at pry/<name>
env - reads from os.environ (PRY_<NAME> or PRY_<name>)
file - reads from PRY_ENV_FILE (default: PRY_DATA_DIR/.env)
auto - tries gopass, falls back to env
Refactored call sites:
auth.py: JWT_SECRET (was: os.getenv + ephemeral random default)
x402.py: X402_WALLET, X402_FACILITATOR_URL (was: os.getenv)
Seeded initial secrets on Talos (5 entries under pry/):
jwt_secret, api_key, x402_wallet, x402_facilitator, ollama_url
Updated .env.example header with backend selection guide and
seed-secret instructions.
Tests: 9/9 in test_secrets_backend.py pass. 36 tests in
test_x402_mcp_spec.py + test_secrets_backend.py all pass.
Verified end-to-end:
>>> import x402
>>> x402.X402_WALLET
'0xYourWalletAddressHere'
>>> import auth
>>> auth.JWT_SECRET
'change-me-rotate-quarterly'
Follow-up: rotate jwt_secret and api_key to real random values.
Document the rotation cadence in SECURITY.md.
The data root was hardcoded as Path(os.path.expanduser("~/.pry")) in
25+ modules, making it impossible to point Pry at a different data
directory (production systemd, Docker volumes, CI scratch, tests).
Changes:
- New module paths.py: single source of truth
PRY_DATA_DIR: Path # read once at import, overridable via env var
subdir(name) -> Path # mkdir+return helper
ensure_data_dir() -> Path # eager init
- 25 modules: replace
X_DIR = Path(os.path.expanduser("~/.pry/x"))
with
X_DIR = PRY_DATA_DIR / "x"
(plus the import; total 53 changes across 26 files)
- .env.example: document PRY_DATA_DIR with examples
- Verified:
- 407 tests collect (was 5 collection errors before fix)
- 83 sampled tests pass
- 0 remaining hardcoded ~/.pry references in py files
Squashed from chore/license-relicense. Full message preserved in the
original branch commit bb77eb5. See ADR-0002 for the decision rationale.
Refs: ADR-0002, commit bb77eb5