validation-claim-audit
Offline, stdlib-only auditor for documented input-checking promises in
Python projects. It reads a project's docs and its Python source, and
reports when a documented checking promise does not match the code.
It executes nothing, uses no network, and never reads .env contents.
Why
Docs that promise input is checked before use, while the code passes user data straight through, fail only on the first hostile or malformed input — the author's own fixtures are always well-formed. The reverse is just as silent: docs that promise unchecked handling, while the code rejects malformed input, surprise the first user who relied on pass-through behaviour. A successful run looks identical either way, so no test fails on the broken promise.
Usage
pip install validation-claim-audit
validation-claim-audit /path/to/project
validation-claim-audit /path/to/project --json
validation-claim-audit /path/to/project --fail-on HIGH
validation-claim-audit /path/to/project --ignore "vendor/*"
Exit codes: 0 PASS, 2 FAIL, 1 usage error. --fail-on HIGH makes
a MEDIUM-only run exit 0 while still printing the MEDIUM findings.
How it works
Claim sources are the root README.md plus docs/**/*.md. Fenced code
blocks are excluded from claims; inline code spans count as prose.
Production Python source excludes tests/, fixtures/, docs/,
examples/, test_*.py, *_test.py, and symlinked files. Checking
evidence found only under tests or fixtures yields MEDIUM findings.
Checking evidence is: imports of a checking library, a checking call, a checking decorator, a model class built on a checking base, or a schema-object load call. Hand-rolled guards with no checking name do not count — see Limitations.
Rules
The exact claim phrases and rule names are listed only in the fenced block below, so that auditing this tool's own tree passes with no claims. Prose in this README deliberately paraphrases them.
Claim families: checked-promise family, unchecked-promise family.
Rules:
documented-validated-claim-false (HIGH)
documented-validated-claim-false-test-only (MEDIUM)
documented-unvalidated-claim-false (HIGH)
documented-unvalidated-claim-false-test-only (MEDIUM)
Claim phrases (checked family):
"validates input", "validates all input", "validates inputs",
"validates user input", "validates data", "validates requests",
"validates arguments", "validates parameters", "input validation",
"all input is validated", "inputs are validated", "validated input",
"validated inputs", "with input validation", "performs validation"
Claim phrases (unchecked family):
"no validation", "without validation", "does not validate",
"never validates", "not validated", "unvalidated",
"no input validation", "without input validation", "does no validation"
Evidence kinds:
import:pydantic, import:jsonschema, import:marshmallow,
import:cerberus, import:voluptuous, call:validate*,
decorator:field_validator, decorator:model_validator,
decorator:validator, decorator:validates, model:BaseModel,
call:schema.load
One finding per family. A checked-promise claim with production checking evidence is verified; an unchecked-promise claim with zero checking evidence anywhere is verified. No claim means PASS, even with checking calls everywhere. A claim with no production Python source at all yields one HIGH finding per family.
Differentiation
- error-claim-audit: which failures the code produces, never whether input is checked before use.
- schema-claim-audit: documented field names vs read/write keys, never whether values are checked.
- security-claim-audit: eval, shell, and pickle execution of data, never checking of data.
- auth-claim-audit: credential requirements, never input checking.
- bandit/ruff: code issues, never docs promises.
- pydantic, jsonschema, and marshmallow documentation: libraries that provide checking, never docs-vs-code truth.
Honest limitations
- Claims are exact phrases, not semantic judgement: a paraphrased promise the phrase list does not contain is missed.
- Matching is word-boundary matching on normalised text (lowercased,
n'texpanded, hyphens turned into spaces). - Negation is asymmetric: a negated sentence suppresses checked-family claims but not unchecked-family claims, because the unchecked family is itself phrased negatively.
- Bare words are not claims: a lone "validate" or "validation" heading promises nothing specific.
- Dead code counts: a checking call in uncalled code is still evidence.
- Imports count even when unused; receiver types are not inferred, so a checking-named attribute call on any receiver counts.
- A file-local function named the same as a checking call suppresses bare-name evidence in that file; attribute evidence is unaffected.
- A schema-object load counts only when the receiver name contains "schema"; other load calls do not count.
- No strength check: this tool checks checking-use existence, not whether a check is strict, complete, or correct. A hand-rolled if/raise guard with no checking name does not count.
- Dynamic imports, aliased library names beyond the tracked list, and checking provided by a framework outside the evidence table are missed.
Development
python3 -m build
PYTHONPATH=src python3 -m unittest discover -s tests -v
License
MIT
Metadata
Release files for validation-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)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| validation_claim_audit-0.1.0.tar.gz | 13.1 kB | Without provenance | Details for validation_claim_audit-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| validation_claim_audit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for validation_claim_audit-0.1.0-py3-none-any.whl |
Total release size: 21.7 kB
Release files / validation_claim_audit-0.1.0.tar.gz
| Download URL | validation_claim_audit-0.1.0.tar.gz |
|---|---|
| Size | 13.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b52268b026201bf1ad25dcd682dc1fec1ac31d24c276f3e85fbb05b29f864853
|
|
BLAKE2b-256 checksum How to use checksums |
30ce608fc197776b7da964e986d11dba28bb9ff346273a74d8229ccb36003d6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / validation_claim_audit-0.1.0-py3-none-any.whl
| Download URL | validation_claim_audit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
907feac72ed6d549dbb2eb8f58d8f169bb7745af246c36e61be88f1f8b4278f8
|
|
BLAKE2b-256 checksum How to use checksums |
87d451beb54dc88f5633fcafbef96a3ba461133b73b71268a20a565559eb062e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for validation-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.