# Audit Open Source Licenses in a Django Project

Yes. An agent resolves your Django lockfile in a sandbox and writes licenses.csv plus licenses.md flagging GPL, AGPL, LGPL, SSPL or unknown licenses.

[Run this on Rush](https://cloud.getrush.ai/run/license-audit/django/).

## What the agent does

The agent clones the project into its sandbox. On a repository like healthchecks/healthchecks it finds a Django 6.1 app (`Django[argon2]==6.1.2` in `requirements.txt`), `manage.py`, the project package under `hc/` (`settings.py`, `urls.py`, apps such as `accounts`, `api`, `front`, `payments`), and two pinned requirement files: `requirements.txt` (runtime: `psycopg==3.3.6`, `pydantic==2.14.1`, `PyJWT[crypto]==2.15.1`, `whitenoise==6.12.0`, `django-compressor==4.6`, `fido2==2.2.1`, and others) and `requirements-dev.txt` (`apprise==1.13.1`, `mypy==2.4.0`, `django-stubs==6.1.2`, `minio==7.2.20`, …). There is no Poetry or pip-tools lockfile; pins live in those two files.

It creates a virtualenv in the sandbox and installs from both files so the full transitive tree is present (pip resolves extras such as `Django[argon2]` and `PyJWT[crypto]`). From the installed set it builds a row per distribution: package name, version, license classifier or METADATA license field, whether it appears in `requirements.txt` / `requirements-dev.txt` (direct) or only as a dependency (transitive), and the dependency path from a top-level requirement to that package.

Extras matter for this tree: `Django[argon2]` pulls the argon2 binder used by the hashers in `hc/settings.py`, and `PyJWT[crypto]` pulls cryptography. Those transitive distributions appear as their own CSV rows with a path that starts at the extra-bearing pin. Editable or VCS requirements are called out if present; Healthchecks' pins are all PyPI versions, so the inventory stays on released distributions.

It then writes `licenses.csv` with those columns and `licenses.md` summarizing anything whose license is GPL, AGPL, LGPL, SSPL, unknown or missing. For each flagged package the Markdown names the top-level requirement that pulls it in (for example a transitive dependency of `apprise` or `django-compressor`) so a lawyer or engineer knows which direct pin to reconsider. The project's own BSD 3-clause license in `LICENSE` is noted as the distribution license of the app itself, separate from dependency licenses.

No application code is modified. The agent does not open a pull request, does not upload packages anywhere, and does not run `manage.py` except if a license tool needs the environment; the deliverables are the CSV and Markdown artifacts.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Clone https://github.com/healthchecks/healthchecks, resolve its full dependency tree from the lockfile, and write licenses.csv (package, version, license, direct or transitive, path from the root) plus licenses.md summarizing any GPL, AGPL, LGPL, SSPL or unknown license and which top-level dependency brings it in."
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is `licenses.csv` and `licenses.md` as session artifacts. The CSV lists every installed distribution with version, license, direct/transitive and the path from a top-level requirement; the Markdown lists only the flagged licenses and the direct dependency responsible.

A reviewer opens the CSV in a spreadsheet, sorts by license, and confirms each flagged path against the team's policy before a release. The transcript keeps the pip install and license-inspection commands so a disputed row can be rechecked.

## Run it on every pull request that changes requirements.txt

On pull requests that touch `requirements.txt` or `requirements-dev.txt`, your server starts this run against the PR branch (pass the branch URL in `resources` or name the ref in the prompt). The report shows whether the change introduced a copyleft or unknown license before merge.

Store the artifact URL on the PR as a comment when `run.completed` arrives so review does not depend on someone running pip-licenses locally.

## Why run it on Rush?

Resolving a Django dependency tree on a laptop means creating a throwaway venv, installing pinned requirements and running a license scanner, then deleting the venv. Rush does that in an isolated sandbox and leaves you the CSV and summary.

Evidence stays with the session: every install line and metadata read is in the transcript. You can audit several services at once without mixing their virtualenvs on one machine.

## Frequently asked questions

### We only have requirements.txt, not a lockfile. Does that still work?

Yes. Healthchecks pins versions in `requirements.txt` and `requirements-dev.txt` without a separate lock. The agent installs those pins and records whatever pip resolves transitively. If you later add a pip-tools or uv lock, point the prompt at that file instead.

### Are dev dependencies included?

Yes for this prompt, because `requirements-dev.txt` is part of the tree. Say "runtime only" in the prompt if you want production pins alone.

### Will it change my requirements files?

No. It only installs into the sandbox and writes `licenses.csv` and `licenses.md`. Your repository stays untouched.

### What counts as unknown?

A distribution with no license field in its metadata, an empty classifier list, or a proprietary marker the scanner cannot map. Those rows appear in `licenses.md` so a person can open the upstream repo.

### Should we exclude requirements-dev.txt for a production image?

Often yes. Re-run with a prompt that installs only `requirements.txt` when the compliance question is about what ships in the container. Keep the full tree for developer-laptop policy questions.
