Skip to main content

readonly-claim-audit

Version 0.1.0. An offline, stdlib-only static auditor for documented read-only claims in Python projects. Python 3.9 or later is required. It reads source and Markdown; it never imports or executes the audited project and makes no network requests. The audit itself does not modify project files.

Installation and use

python3 -m pip install .
readonly-claim-audit .
readonly-claim-audit . --json
readonly-claim-audit . --fail-on HIGH --verbose
readonly-claim-audit . --ignore documented-readonly-write
readonly-claim-audit --version

The path defaults to the current directory. Exit 0 means PASS, 2 means FAIL, and 1 means a usage or input error (including invalid Python or unreadable input). The default failure threshold is MEDIUM. --fail-on HIGH still prints MEDIUM findings but returns 0 for those alone. --ignore RULE,... removes matching findings before deciding status. --verbose includes verified claims in human output. --version prints 0.1.0.

JSON contains status, findings, and verified_claims. Each finding has rule, severity, file, line, and message. Paths are relative to the project root; lines are one-based. Human finding lines use SEVERITY rule file:line message, followed by the overall status.

Claims and rules

Claims come only from root README.md and docs/**/*.md, excluding backtick and tilde fenced blocks. Case-insensitive patterns are: read-only/read only; does not modify/doesn't modify/never modifies/never modify; does not write/ doesn't write/never writes/never write/no writes; does not change/never changes. The change phrases are interpreted in the filesystem context; semantic context is not inferred. A claim is a unique (file, line, kind) triple. Repeated phrases of one kind on one line produce one claim. Positive statements such as “writes a report” are not claims.

  • documented-readonly-write (HIGH): claims and production write evidence.
  • documented-readonly-write-test-only (MEDIUM): claims and writes exclusively in test files. A test file is under tests/ or fixtures/, or named test_*.py or *_test.py, at any depth.
  • If production writes exist, report those; the test-only rule does not apply.
  • One finding per (rule, evidence-file, evidence-line), regardless of claim count. Three writes on different lines yield three findings. Multiple write calls on one line yield one finding naming a representative call.
  • No Python source means HIGH findings at each claim location, one per claim.
  • No claims means PASS, even with writes. There are no reverse rules.

Verified claims are claims with Python source present and no write evidence. Ignoring a finding does not turn its claims into verified claims.

Static write-evidence table

Calls Evidence
open, io.open Literal positional or mode= string containing w, a, x, or +
Any receiver's write_text, write_bytes Always
os.remove, os.unlink, os.rename, os.replace Always
os.mkdir, os.makedirs, os.rmdir, os.removedirs Always
shutil.copy, shutil.copy2, shutil.move, shutil.rmtree Always
os.chmod, os.utime Excluded: metadata-only
print(..., file=...) Excluded: the opening call provides evidence

Read modes r and rb and omitted modes are not evidence. Variable or computed modes are UNKNOWN and skipped, even if a nearby assignment is a literal. Symlinked source/docs files and symlink directories are skipped. .env contents are never read. No target files are opened for writing.

Differentiation

Bandit and Ruff detect code issues, rather than documentation promises. privacy-claim-audit covers network/telemetry evidence. The format, schema, API, and config claim auditors cover formats, fields, symbols, and defaults rather than filesystem writes. find . -writable and permission checks measure actual writability, without comparing documentation claims. No tool specifically comparing documented read-only promises with static source writes is known to this project's authors; this is not an exhaustive market claim.

Limitations

PASS is not a proof of runtime safety. This tool does no call-graph, reachability, alias, data-flow, or semantic prose analysis. Dead code counts. Imported aliases, wrappers, dynamically selected methods, subprocesses, native extensions, other languages, and unlisted write APIs can evade detection. Any receiver with a write_text or write_bytes attribute counts, without requiring a pathlib import; unrelated methods can therefore produce false positives. Names such as os can be shadowed and still count. Claims are project-wide, so qualified or negated prose may be overinterpreted. Inline code is not excluded. Only fenced blocks are excluded; complex Markdown constructs are not fully parsed.

All regular .py files under the target are scanned, including vendored code and virtual environments; choose a clean project tree. UTF-8 text and parseable Python are required. Static checks do not establish actual filesystem permissions. The auditor reads input without a snapshot, so concurrent filesystem changes can affect results. Metadata writes and print destinations are excluded as specified above. Findings should be reviewed by a person.

Development

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

MIT licensed. No runtime dependencies.

Metadata

Release files for readonly-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 readonly-claim-audit 0.1.0
File Size Uploaded Provenance Actions
readonly_claim_audit-0.1.0.tar.gz 9.0 kB Without provenance Details for readonly_claim_audit-0.1.0.tar.gz

Built distribution (wheel)

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

Total release size: 16.6 kB

Release files / readonly_claim_audit-0.1.0.tar.gz

Download URL readonly_claim_audit-0.1.0.tar.gz
Size 9.0 kB
Tags Source
SHA-256 checksum
How to use checksums
5dbd7b3a8ebf74ca885dd06dfced94cab74e33298e41673fa9d7b0a75116c734
BLAKE2b-256 checksum
How to use checksums
714305a752b129b7f65e8b19364895bcee2d7eaa5a4a7aaa8510378706026bce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

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

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

Security for readonly-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