Skip to main content

lenscheck-contract

Your backend keeps a list of what it does. And it can't lie about it.

Companion library to lenscheck-semantic-reviewer. Lenscheck reads code from outside and guesses. This runs inside your app and knows.

What it does

While your app starts, it records:

  • every route (path, method, auth)
  • every model (fields, types, constraints)
  • every outside call (HTTP, email, payments)
  • every background job
  • how much of that it actually knows vs. couldn't figure out

Then you can ask your app one question and get an answer:

"What does this app actually do?"

Why it matters

AI opens a PR with 400 changed lines. You don't read them. You read this:

RISKY (4)
  POST /orders         auth: user -> public
  POST /orders         new effect: net:analytics.example.com
  shop.Customer.email  unique: True -> False
  shop.Customer.name   field removed (data loss)

Four lines instead of four hundred.

Install

pip install lenscheck-contract

Use it — three levels

Level 1: nothing to write

Works on an existing Django project with zero code changes.

lenscheck-contract export --settings myproject.settings -o contract.json

It reads Django's real router and real model registry. Routes built in loops, DRF routers, mixins — all found, because the app already resolved them at startup.

Coverage will be partial. That's reported, not hidden:

wrote contract.json: 9 routes, 6 models, 0 jobs, auth known on 5/9

Level 2: declare what matters

from lenscheck_contract import contract

@contract.route("POST /orders", auth="user")
@contract.effects("net:api.stripe.com")
def create_order(request):
    ...

Eight decorators total, max. AI writes these correctly first try, because they look like every Django decorator it has ever seen.

Level 3: enforce it

# settings.py
MIDDLEWARE = ["lenscheck_contract.middleware.ContractMiddleware", ...]

# conftest.py or apps.py
from lenscheck_contract import guard
guard.install(mode="error")   # off | record | warn | error

Now an undeclared call fails loudly:

shop.views.leaky_order performed undeclared effect 'net:api.stripe.com'.
Declared: none. Add @contract.effects('net:api.stripe.com') or remove the call.

This is the part no linter can do. The bad code doesn't ship.

Don't know what to declare? Run your tests in record mode and let it tell you:

guard.install(mode="record")
# ... run test suite ...
json.dump(guard.suggestions(), open("observed.json", "w"))
lenscheck-contract suggest observed.json     # prints the decorators to paste in

In CI

- run: lenscheck-contract export --settings myproject.settings -o head.json
- run: git checkout ${{ github.base_ref }}
- run: lenscheck-contract export --settings myproject.settings -o base.json
- run: lenscheck-contract diff base.json head.json --markdown --fail-on risky

--fail-on risky exits 1 on auth weakening, new outside calls, dropped fields, relaxed uniqueness, or changed relations.

How the effect guard works

One hook at the socket layer, not per-library. requests, httpx, urllib, boto3, stripe — all covered by the same code, including libraries that don't exist yet.

  • socket.getaddrinfo is checked before it runs, so a blocked call never leaves the process
  • socket.socket.connect catches direct-IP connections
  • smtplib.SMTP.sendmail catches email
  • localhost and unix sockets are never effects, so your database doesn't trip it

Patterns support wildcards: net:*.stripe.com, net:*, email.

What it does not catch

Worth being blunt about.

  • Business logic. If AI changes a discount from 10% to 90%, the contract is identical. Routes same, models same, effects same. Tests catch that; this doesn't.
  • Anything the router never sees. Dead code, unmounted views.
  • Dynamic hostnames are caught at runtime, not at export time. The contract records what you declared; the guard records what actually happened.

Structural mistakes: this. Logic mistakes: your tests. You need both.

Try it

git clone ... && cd lenscheck-contract
pip install -e ".[dev]"
pytest
cd examples/demo && lenscheck-contract export --settings settings --root . -o /tmp/base.json

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lenscheck_contract-1.0.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lenscheck_contract-1.0.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file lenscheck_contract-1.0.0.tar.gz.

File metadata

  • Download URL: lenscheck_contract-1.0.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lenscheck_contract-1.0.0.tar.gz
Algorithm Hash digest
SHA256 89ff9260e4ae455f22c9ea31ae824b969db85cc60a67cac3323ea9f1518357a3
MD5 a17a387c6a40f348fed0ed2c3fdd6d24
BLAKE2b-256 5deebd29df6363458ab41fc8901f27373d3ade8be577f67a7464831a8f1ad939

See more details on using hashes here.

Provenance

The following attestation bundles were made for lenscheck_contract-1.0.0.tar.gz:

Publisher: publish.yml on AnkushSinghGandhi/lenscheck-contract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lenscheck_contract-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lenscheck_contract-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b4aaf24f50a21fa80c5182e73c43eb106ba06a809901c28e6dc26fea2aaddb75
MD5 5bcdfe49ebff64867c46a83e8f7be8bd
BLAKE2b-256 9b1e32bb567d881ba4a1aa65ad2158c38484886fa7ea52d0201839ce7d596a94

See more details on using hashes here.

Provenance

The following attestation bundles were made for lenscheck_contract-1.0.0-py3-none-any.whl:

Publisher: publish.yml on AnkushSinghGandhi/lenscheck-contract

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

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