Skip to main content

logging-claim-audit

Offline, stdlib-only audit of documented record-keeping promises in a Python project against its Python source. It reads docs and code, runs nothing, uses no network, and never opens the contents of any environment file.

A project can promise three kinds of record-keeping behaviour, and each can drift from the code without any test failing:

  • a file-sink promise: records are kept in a file the user can find later;
  • a machine-readable record promise: records are emitted in a shape a parser can consume directly;
  • an absence-of-records promise: the tool keeps nothing at all.

The first two fail quietly when the code never builds the corresponding mechanism. The third fails quietly in the other direction: a user who was told nothing is kept discovers records the docs said would not exist. This tool checks all three directions statically, from prose in the root README and docs/**/*.md against imports and calls in production Python source.

Installation

pip install logging-claim-audit

Or from source:

python3 -m pip install .

Usage

logging-claim-audit /path/to/project
logging-claim-audit /path/to/project --json
logging-claim-audit /path/to/project --fail-on HIGH
logging-claim-audit /path/to/project --ignore "vendor/*"

Exit codes: 0 means pass, 2 means at least one finding at or above the --fail-on threshold (default MEDIUM), 1 means a usage error. --verbose prints verified promises. --json prints findings and verified promises as JSON.

Rules

documented-file-log-claim-false (HIGH)
  file-sink promise present, zero file-sink evidence in production
  source and zero file-sink evidence under tests/fixtures only.
documented-file-log-claim-false-test-only (MEDIUM)
  file-sink promise present, zero production file-sink evidence, but
  file-sink evidence under tests/fixtures only.
documented-structured-log-claim-false (HIGH)
  machine-readable record promise present, zero machine-readable
  evidence in production source and zero under tests/fixtures only.
documented-structured-log-claim-false-test-only (MEDIUM)
  machine-readable record promise present, zero production
  machine-readable evidence, but such evidence under tests/fixtures only.
documented-no-log-claim-false (HIGH)
  absence-of-records promise present, but production source contains
  record-keeping evidence (any of the kinds below).
documented-no-log-claim-false-test-only (MEDIUM)
  absence-of-records promise present, zero production record-keeping
  evidence, but such evidence under tests/fixtures only.

Claim phrases (exact phrases only, matched on normalised prose with word boundaries; fenced code blocks are excluded, inline code counts):

file-sink family:
  "logs to a file", "writes logs to a file", "write logs to a file",
  "logs are written to a file", "log file", "log files"
machine-readable family:
  "structured logging", "structured logs", "json logs",
  "logs in json format", "logs as json", "json formatted logs"
absence family:
  "no logging", "does not log", "never logs", "no logs",
  "without logging", "does not log anything", "never logs anything"

Negation on a sentence suppresses the file-sink and machine-readable families on that sentence, but not the absence family (whose phrases are themselves negative wordings). A denial scoped to a file sink only (for example a sentence saying records are never written to a file) yields no promise of either kind and is not audited. One finding per family at most; a tree with no production Python source at all yields one HIGH finding per promised family; a tree with no promise yields a pass even if record-keeping calls are everywhere.

Evidence (production source only; tests/, fixtures/, docs/, examples/, and symlinked files are excluded from production evidence):

  • File-sink evidence: FileHandler family calls (FileHandler, RotatingFileHandler, TimedRotatingFileHandler, WatchedFileHandler), basicConfig with a filename keyword whose value is not None, and loguru logger.add with a string file sink.
  • Machine-readable evidence: structlog / pythonjsonlogger imports, JsonFormatter calls, loguru logger.add(serialize=True), and a record-keeping call whose argument is a json.dumps(...) call.
  • Any-record evidence (falsifies an absence promise): all of the above, plus any record-keeping library import, any record-keeping call on a receiver whose dotted name contains log, and getLogger calls.
  • A bare name that is redefined in the same file (a local function, class, or parameter with the same name) suppresses name-based evidence for that name in that file; attribute-based evidence is unaffected.

Differentiation

  • silent-claim-audit: output volume (quiet/verbose), never whether records go through a record-keeping framework or to a file sink.
  • format-claim-audit: data formats read/written, never the shape or destination of the tool's own operational records.
  • privacy-claim-audit: network/telemetry presence, never local record keeping.
  • bandit/ruff: code issues, never docs promises.
  • logging / structlog / loguru documentation: libraries that provide record keeping, never docs-vs-code truth.

Honest limitations

  • Static pattern matching, not semantic judgement: a file-sink call in dead code counts as evidence, and an unused record-keeping import counts as evidence. Both are intentional over-approximations.
  • A variable sink value is unknown and skipped; only string-literal sinks count for loguru file sinks.
  • basicConfig(filename=None) and serialize=False are explicitly not evidence.
  • dictConfig contents are not parsed: a file handler named only inside a configuration dict literal is missed. This is the main recall gap alongside print-based records: print(json.dumps(...)) is not a record-keeping call and is not counted.
  • A plain Formatter with a format string is not machine-readable evidence by itself.
  • A bare .info on a receiver whose name contains no log is not a record-keeping call.
  • This tool checks record-keeping existence, destination, and shape — not whether records are complete, rotated, or actually flushed.

Development

PYTHONPATH=src python3 -m unittest discover -s tests -v
python3 -m build

Requires Python 3.9 or later. Standard library only, no dependencies.

Metadata

Release files for logging-claim-audit 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for logging-claim-audit 0.1.0
File Size Uploaded Provenance Actions
logging_claim_audit-0.1.0.tar.gz 14.9 kB Without provenance Details for logging_claim_audit-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for logging-claim-audit 0.1.0
File Interpreter ABI Platform Actions
logging_claim_audit-0.1.0-py3-none-any.whl Python 3 none any Details for logging_claim_audit-0.1.0-py3-none-any.whl

Total release size: 24.4 kB

Release files / logging_claim_audit-0.1.0.tar.gz

Download URL logging_claim_audit-0.1.0.tar.gz
Size 14.9 kB
Tags Source
SHA-256 checksum
How to use checksums
bd01d56821aaf84a8644278170fa72a6fe736e7b975c25dacc4c67bc55ed946c
BLAKE2b-256 checksum
How to use checksums
e537df09f6b82fced132164bf6680a958e199c3f24dae8ffceddbea889f5552e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / logging_claim_audit-0.1.0-py3-none-any.whl

Download URL logging_claim_audit-0.1.0-py3-none-any.whl
Size 9.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0368907e50ed16cda80d519598119df79062fb128558f302f65baac6782d7f49
BLAKE2b-256 checksum
How to use checksums
f16784df1c5fe1fa7e801c90f4daa770e16fe236cc0a519b9b00f77e87241c6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for logging-claim-audit 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page