Skip to content

Repository files navigation

ConfigLedger

CI License Python

Find configuration drift across code, examples, CI, containers, deployment YAML, and docs—without collecting secret values.

ConfigLedger is a local, deterministic CLI for answering questions that are surprisingly hard in a real repository:

  • Where is DATABASE_URL consumed, delivered, exemplified, and documented?
  • Which active keys have no documented setup path?
  • Which sample or deployment defaults disagree?
  • Which example keys are unused?
  • Did someone put a literal value next to a sensitive-looking key?

It runs offline, executes no repository code, needs no account, and sends nothing to an AI service.

$ configledger scan examples/demo --no-cache --fail-on none
ConfigLedger
Scanned 4 artifacts; found 4 configuration keys.
Findings: 1 critical, 2 high, 2 medium, 1 low.

[CRITICAL] config.sensitive-literal — SUPPORT_TOKEN
  SUPPORT_TOKEN looks sensitive and has a non-placeholder literal in an example surface.
  - .env.example:3 (example)
  - app.py:5 (consumption)

[HIGH] config.undefined-consumption — ANALYTICS_KEY
  ANALYTICS_KEY is consumed but no definition, example, or delivery surface was found.
  - app.py:4 (consumption)

Why ConfigLedger exists

Environment and configuration keys are duplicated across source code, .env.example, Docker, CI, Kubernetes, and documentation. Format-specific linters see one file type; secret scanners look for leaked values. ConfigLedger builds a source-linked, per-key provenance record across all of those surfaces and evaluates transparent drift rules.

ConfigLedger does not replace a secret manager, configuration loader, or vulnerability scanner. It deliberately analyzes names and safe metadata—not runtime values.

Install

ConfigLedger requires Python 3.12 or newer.

python -m pip install configledger

For development or before the first package-index release:

git clone https://github.com/DevFoundry-labs/configledger.git
cd configledger
python -m pip install .

Quick start

Scan the current repository:

configledger scan .

Try the reproducible included demo without letting findings change the shell exit code:

configledger scan examples/demo --no-cache --fail-on none

Export machine-readable or review-friendly output:

configledger scan . --format json --output configledger-report.json
configledger scan . --format markdown --output configledger-report.md
configledger scan . --format schema --output .env.generated.example

Inspect one key:

configledger show DATABASE_URL .

Supported evidence surfaces

Surface Evidence recognized in v0.1
Python os.getenv, os.environ, Pydantic-style settings and aliases
JavaScript / TypeScript process.env.KEY, indexed access, import.meta.env.KEY
Dotenv examples .env.example, .env.sample, .env.template
Dockerfile ARG, ENV, and variable references
Docker Compose / YAML environment, env, and interpolated variables
GitHub Actions env, vars, and secrets references
Kubernetes-like YAML env entries and name keys (confidence-tagged)
Markdown Backticked keys, tables, and key/value-style references

Unsupported or ambiguous syntax is reported as a diagnostic or omitted. ConfigLedger never treats incomplete static evidence as proof that runtime configuration is safe.

Rules

Rule Default severity Meaning
config.undefined-consumption High A consumed key has no definition, example, or delivery evidence.
config.unused-declaration Low A defined/example key has no consumption or delivery evidence.
config.undocumented Medium An active key has no Markdown documentation evidence.
config.default-drift High Non-secret default fingerprints disagree across surfaces.
config.sensitive-literal Critical A sensitive-looking key has a non-placeholder literal in an example.

List rules from the installed version:

configledger rules

Configuration

Create .configledger.toml at the repository root:

[scan]
ignore_paths = ["vendor/**", "generated/**"]
ignore_keys = ["TEST_ONLY_*"]
internal_keys = ["CI", "INTERNAL_*"]
max_files = 5000
max_file_bytes = 1000000
max_total_bytes = 25000000

[rules]
disabled = ["config.unused-declaration"]
fail_on = "high" # info, low, medium, high, critical, or none

[rules.severity]
"config.undocumented" = "low"

Command-line --fail-on overrides the policy for that run. See configuration reference.

Baselines

Baselines contain finding fingerprints, not configuration values:

configledger baseline create .configledger-baseline.json .
configledger baseline compare .configledger-baseline.json .

The compare command exits with status 1 when new fingerprints appear.

Exit codes

Code Meaning
0 Scan completed and no finding met the failure threshold.
1 Findings met the threshold, a key was not found, or baseline comparison found new findings.
2 Invalid path, policy, report path, or other usage error.
3 Reserved for unexpected internal failures.

Privacy and security

  • .env, .env.local, private keys, binaries, and common dependency/build directories are excluded before reading.
  • Example/deployment literals are represented by hashes and redacted excerpts; raw values are not stored in reports or SQLite.
  • Repository modules, scripts, containers, and workflows are never executed.
  • Discovery is bounded and rejects out-of-root symlink reads.
  • Core operation is offline and has no telemetry or AI provider.

Read the threat model and security policy before scanning untrusted repositories in sensitive environments.

Architecture

safe discovery → format extractors → normalized occurrences
      → per-key provenance → deterministic rules → reports / SQLite cache

The CLI, library API, persistence model, and reporter boundaries are described in architecture.md. The versioned JSON contract is scan-result.schema.json.

Development

python -m venv .venv
# Windows: .venv\Scripts\activate
# macOS/Linux: source .venv/bin/activate
python -m pip install -e ".[dev]"
ruff format --check .
ruff check .
mypy src
pytest --cov=configledger --cov-report=term-missing
python -m build

See CONTRIBUTING.md for extractor and rule contribution guidance.

Roadmap

  • v0.1: Local inventory, six extractor families, five rules, four report formats, baselines, SQLite cache.
  • v0.2: SARIF, richer framework adapters, GitHub Action annotations, ignore explanations.
  • v0.3: Stable extractor SDK and community compatibility fixtures.

The project will remain local-first and deterministic. New features must improve configuration provenance rather than turn ConfigLedger into a secret manager or generic code-intelligence platform.

License

Apache License 2.0. See LICENSE.

About

Secret-safe configuration provenance and drift detection across code, CI, containers, deployment manifests, and docs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages