codelaw-rules-deps 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arpit Arya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ SPDX-License-Identifier: MIT
@@ -0,0 +1,9 @@
1
+ @codelaw/rules-deps / codelaw-rules-deps
2
+
3
+ The rules and their documentation were written for codelaw. The pack holds no
4
+ advisory data: `codelaw deps refresh` writes the consumer's own
5
+ `.codelaw/deps-snapshot.json`, which keeps, of each advisory, only its ids and
6
+ aliases, its affected ranges and fixed versions, its severity, its URL and the
7
+ sources that reported it — never an advisory's text. Advisory data from OSV and
8
+ the GitHub Advisory Database is licensed CC-BY 4.0 by its publishers; the
9
+ snapshot's `sources` names where each record came from.
@@ -0,0 +1,64 @@
1
+ # @codelaw/rules-deps
2
+
3
+ codelaw's dependency rules — one of the first-party rule packs
4
+ ([SR-RULE-PACKS](../../records/0101_rule-packs.md) decision 15), on npm and
5
+ PyPI (`codelaw-rules-deps`). It tells you, and your coding agent, which npm
6
+ and Python dependencies are vulnerable and the exact version to move to, and
7
+ which are behind their latest release.
8
+
9
+ `codelaw init` adds it when the repo has a `package.json` or `pyproject.toml`.
10
+
11
+ ```toml
12
+ # codelaw.toml
13
+ extends = ["codelaw:deps/recommended"]
14
+ preview = true # every rule is `preview` until a corpus run promotes it
15
+ ```
16
+
17
+ ```sh
18
+ npm i -D @codelaw/rules-deps # or
19
+ pip install codelaw-rules-deps
20
+ codelaw deps refresh # the one command that reads the network
21
+ ```
22
+
23
+ ## Presets
24
+
25
+ <!-- docs-sync:presets -->
26
+
27
+ | preset | rules | what it holds |
28
+ |---|---|---|
29
+ | `deps/recommended` | 4 | Vulnerable and outdated dependencies of package.json and pyproject.toml, from the committed snapshot `codelaw deps refresh` writes |
30
+
31
+ <!-- /docs-sync:presets -->
32
+
33
+ ## Rules
34
+
35
+
36
+
37
+ | rule | fix | what it reports |
38
+ |---|---|---|
39
+ | `deps/vulnerable` | suggest (manual with no clean version) | a version in use, direct or transitive, that an advisory affects, with the lowest known-clean version to move to |
40
+ | `deps/incomplete-scan` | manual | an enabled advisory source the last refresh could not read |
41
+ | `deps/outdated` | suggest | a dependency behind its latest version, or a deprecated or yanked one (was `data/outdated-dependency`) |
42
+ | `deps/stale-snapshot` | manual | a snapshot older than `[deps] max_snapshot_age`, or one that cannot be read (was `data/stale-deps-snapshot`) |
43
+
44
+
45
+
46
+ ## How it works
47
+
48
+ The rules read `.codelaw/deps-snapshot.json`, which `codelaw deps refresh`
49
+ writes and the project commits, and the lockfiles — never the network, so
50
+ `codelaw check` gives the same answer offline and in CI.
51
+
52
+ - **Advisory sources** are `[deps] advisory_sources`, each on or off:
53
+ `registry` (the npm registry and Python index you already install from)
54
+ first, then `osv` (`https://api.osv.dev`), or a mirror of either. Every
55
+ enabled source is read and merged — the safer answer wins. A source that
56
+ cannot be read is recorded, and `deps/incomplete-scan` says so.
57
+ - **The version to move to** is the lowest version every advisory leaves
58
+ clean and some source actually covered, inside the major in use first.
59
+ - **Agents** ask `check_dependency` (MCP) or `codelaw deps check` before
60
+ adding a package; `[deps] agent` sets, per severity, whether the hooks
61
+ only inform or also block.
62
+
63
+ The pack holds no advisory data: the snapshot keeps ids, ranges, versions, a
64
+ severity, a URL and the sources' names — never an advisory's text.
@@ -0,0 +1,6 @@
1
+ name = "@codelaw/rules-deps"
2
+ version = "0.4.2"
3
+ min_codelaw = "0.4.0"
4
+ languages = ["json", "yaml", "toml"]
5
+ presets = ["deps/recommended"]
6
+ description = "codelaw's dependency rules: vulnerable packages and the version to move to, latest versions, the snapshot they read (SR-RULE-PACKS)"
@@ -0,0 +1,8 @@
1
+ # `codelaw test --corpus` finding counts (SR-RULE-AUTHORING decision 4).
2
+ # Rewrite with --update-snapshot, and review the change.
3
+
4
+ [findings]
5
+ "deps/incomplete-scan" = 0
6
+ "deps/outdated" = 0
7
+ "deps/stale-snapshot" = 0
8
+ "deps/vulnerable" = 0
@@ -0,0 +1,7 @@
1
+ description = "Vulnerable and outdated dependencies of package.json and pyproject.toml, from the committed snapshot `codelaw deps refresh` writes"
2
+
3
+ [rules]
4
+ "deps/incomplete-scan" = "warn"
5
+ "deps/outdated" = "warn"
6
+ "deps/stale-snapshot" = "info"
7
+ "deps/vulnerable" = "error"
@@ -0,0 +1,94 @@
1
+ ---
2
+ id: deps/incomplete-scan
3
+ title: "Every advisory source was read"
4
+ languages: [json, toml]
5
+ files: ["package.json", "pyproject.toml"]
6
+ severity: warn
7
+ fix: manual
8
+ fix_reason: "reading an advisory source again needs the network, which the engine never uses (L5); turning a source off is the team's decision"
9
+ stability: preview
10
+ since: 0.5.0
11
+ ---
12
+
13
+ `.codelaw/deps-snapshot.json` records how each advisory source of `[deps] advisory_sources` answered the last `codelaw deps refresh`. While a source that is still enabled was `unavailable` — refused by a proxy, down, or a mirror that does not pass the audit endpoint through — the vulnerabilities only it knows are not reported, and this rule says so: one finding per project, naming each such source, its day and its error, on the root `package.json` (else the root `pyproject.toml`). A snapshot that holds packages but no source at all — written before the advisory sources, or with every source turned off — is reported too.
14
+
15
+ **Why:** A clean `deps/vulnerable` result means "no source we read knows of one"; when a source was not read, a clean result says less than it seems to.
16
+
17
+ ```codelaw
18
+ native: deps/incomplete-scan
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Run `codelaw deps refresh` once the source is reachable, and commit the snapshot.
24
+ 2. If the organisation will never allow that source, set `enabled = false` on it in `[deps] advisory_sources`, so the scan is complete as configured.
25
+
26
+ ## Examples
27
+
28
+ ### JSON
29
+
30
+ #### Don't
31
+
32
+ ```json
33
+ // .codelaw/deps-snapshot.json
34
+ {
35
+ "fetched": "2026-10-29",
36
+ "packages": {},
37
+ "sources": {
38
+ "osv": { "kind": "osv", "state": "unavailable", "on": "2026-10-29", "error": "https://api.osv.dev/v1/query answered HTTP 403" },
39
+ "registry": { "kind": "registry", "state": "ok", "on": "2026-10-29" }
40
+ }
41
+ }
42
+ // package.json
43
+ {
44
+ "name": "app"
45
+ }
46
+ ```
47
+
48
+ #### Do
49
+
50
+ ```json
51
+ // .codelaw/deps-snapshot.json
52
+ {
53
+ "fetched": "2026-10-29",
54
+ "packages": {},
55
+ "sources": {
56
+ "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" },
57
+ "registry": { "kind": "registry", "state": "ok", "on": "2026-10-29" }
58
+ }
59
+ }
60
+ // package.json
61
+ {
62
+ "name": "app"
63
+ }
64
+ ```
65
+
66
+ ### TOML
67
+
68
+ #### Don't
69
+
70
+ ```toml
71
+ # .codelaw/deps-snapshot.json
72
+ {
73
+ "fetched": "2026-10-29",
74
+ "packages": {},
75
+ "sources": { "osv": { "kind": "osv", "state": "unavailable", "on": "2026-10-29", "error": "HTTP 403" } }
76
+ }
77
+ # pyproject.toml
78
+ [project]
79
+ name = "app"
80
+ ```
81
+
82
+ #### Do
83
+
84
+ ```toml
85
+ # .codelaw/deps-snapshot.json
86
+ {
87
+ "fetched": "2026-10-29",
88
+ "packages": {},
89
+ "sources": { "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" } }
90
+ }
91
+ # pyproject.toml
92
+ [project]
93
+ name = "app"
94
+ ```
@@ -0,0 +1,112 @@
1
+ ---
2
+ id: deps/outdated
3
+ title: "Dependencies are on their latest version"
4
+ languages: [json, toml]
5
+ files: ["**/package.json", "**/pyproject.toml"]
6
+ fix: suggest
7
+ fix_reason: "a new major or minor version can change behaviour; the fix moves the range to the latest version, and the code that uses the package may need changes"
8
+ stability: preview
9
+ since: 0.3.0
10
+ ---
11
+
12
+ Each dependency of a `package.json` (`dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`) and of a `pyproject.toml` (`[project] dependencies`, `[project.optional-dependencies]`, `[dependency-groups]`) is compared with `.codelaw/deps-snapshot.json`, the registry facts `codelaw deps refresh` wrote. The rule reads only that file and the lockfiles; it never reads a registry, so `check` gives the same answer offline. With no snapshot, nothing is reported.
13
+
14
+ The version in use is the lockfile's (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `uv.lock` or `poetry.lock`, beside the manifest or above it), else the one the range starts from. The latest is the highest stable version in the snapshot — by semver for npm, PEP 440 for Python — that is not deprecated or yanked and is at least `[deps] min_release_age` old on the snapshot's `fetched` date.
15
+
16
+ Each finding is graded, and `[deps] severity` sets each grade's severity (or `off`):
17
+
18
+ | finding | default |
19
+ |---|---|
20
+ | a major version behind | `warn` |
21
+ | a minor or patch version behind | `info` |
22
+ | the version in use is deprecated (npm) or yanked (PyPI) | `error` |
23
+ | the range already allows the latest, but the lockfile is behind | `info` |
24
+
25
+ The fix moves the range's version to the latest and keeps its operator: `^`, `~`, `>=`, `=` or none for npm; `==`, `>=` or `~=` for Python, at the precision written (`~=4.2` becomes `~=5.1`). A range the fix can't move without changing its meaning — `||`, a hyphen, `x`, an upper bound the latest is outside — is reported without a fix. `[deps] ignore` names packages never reported.
26
+
27
+ **Why:** A dependency left behind stops getting fixes and security patches, and the jump grows with every release; a deprecated or yanked version was withdrawn by its own maintainers.
28
+
29
+ ```codelaw
30
+ native: deps/outdated
31
+ ```
32
+
33
+ ## How to fix
34
+
35
+ 1. Run `codelaw fix --unsafe` to move the range to the latest version, or edit the version by hand.
36
+ 2. Run your package manager's install (`npm install`, `uv lock`, …) so the lockfile follows.
37
+ 3. For a major version, read the package's changelog and update the code that uses it.
38
+ 4. If the project must stay on this version, add the package to `[deps] ignore`, with an `expires` date when the stay is temporary.
39
+
40
+ ## Examples
41
+
42
+ ### JSON
43
+
44
+ #### Don't
45
+
46
+ ```json
47
+ // .codelaw/deps-snapshot.json
48
+ {
49
+ "fetched": "2026-10-25",
50
+ "packages": {
51
+ "npm:react": { "latest": "19.2.0", "versions": { "18.3.1": "2024-04-26", "19.2.0": "2025-10-01" } }
52
+ }
53
+ }
54
+ // package.json
55
+ {
56
+ "dependencies": {
57
+ "react": "^18.3.1"
58
+ }
59
+ }
60
+ ```
61
+
62
+ #### Do
63
+
64
+ ```json
65
+ // .codelaw/deps-snapshot.json
66
+ {
67
+ "fetched": "2026-10-25",
68
+ "packages": {
69
+ "npm:react": { "latest": "19.2.0", "versions": { "18.3.1": "2024-04-26", "19.2.0": "2025-10-01" } }
70
+ }
71
+ }
72
+ // package.json
73
+ {
74
+ "dependencies": {
75
+ "react": "^19.2.0"
76
+ }
77
+ }
78
+ ```
79
+
80
+ ### TOML
81
+
82
+ #### Don't
83
+
84
+ ```toml
85
+ # .codelaw/deps-snapshot.json
86
+ {
87
+ "fetched": "2026-10-25",
88
+ "packages": {
89
+ "pypi:django": { "latest": "5.1.2", "versions": { "4.2.0": "2023-04-03", "5.1.2": "2024-10-08" } }
90
+ }
91
+ }
92
+ # pyproject.toml
93
+ [project]
94
+ name = "app"
95
+ dependencies = ["django~=4.2"]
96
+ ```
97
+
98
+ #### Do
99
+
100
+ ```toml
101
+ # .codelaw/deps-snapshot.json
102
+ {
103
+ "fetched": "2026-10-25",
104
+ "packages": {
105
+ "pypi:django": { "latest": "5.1.2", "versions": { "4.2.0": "2023-04-03", "5.1.2": "2024-10-08" } }
106
+ }
107
+ }
108
+ # pyproject.toml
109
+ [project]
110
+ name = "app"
111
+ dependencies = ["django~=5.1"]
112
+ ```
@@ -0,0 +1,72 @@
1
+ ---
2
+ id: deps/stale-snapshot
3
+ title: "The dependency snapshot is recent"
4
+ languages: [json, toml]
5
+ files: ["package.json", "pyproject.toml"]
6
+ severity: info
7
+ fix: manual
8
+ fix_reason: "refreshing the snapshot reads the registries, which needs the network; the engine never uses it (L5)"
9
+ stability: preview
10
+ since: 0.3.0
11
+ ---
12
+
13
+ `.codelaw/deps-snapshot.json` — the registry facts `deps/outdated` reads — was fetched no more than `[deps] max_snapshot_age` (14 days by default) before the as-of date, and can be read. The finding is on the root `package.json`, or the root `pyproject.toml` when there is no root `package.json`, so a project gets one. The age is judged on the as-of date (`--as-of`, `CODELAW_AS_OF`, else `HEAD`'s commit date), never the clock; with no as-of date, only an unreadable snapshot is reported.
14
+
15
+ **Why:** An old snapshot hides every release since it was written, so `deps/outdated` says a dependency is current when it isn't.
16
+
17
+ ```codelaw
18
+ native: deps/stale-snapshot
19
+ ```
20
+
21
+ ## How to fix
22
+
23
+ 1. Run `codelaw deps refresh`: it reads npm and the Python index and writes the snapshot again.
24
+ 2. Commit `.codelaw/deps-snapshot.json`, so CI and every teammate judge by the same facts.
25
+
26
+ ## Examples
27
+
28
+ ### JSON
29
+
30
+ #### Don't
31
+
32
+ ```json
33
+ // .codelaw/deps-snapshot.json
34
+ { "fetched": "2026-10-25", "packages": [ }
35
+ // package.json
36
+ {
37
+ "name": "app"
38
+ }
39
+ ```
40
+
41
+ #### Do
42
+
43
+ ```json
44
+ // .codelaw/deps-snapshot.json
45
+ { "fetched": "2026-10-25", "packages": {} }
46
+ // package.json
47
+ {
48
+ "name": "app"
49
+ }
50
+ ```
51
+
52
+ ### TOML
53
+
54
+ #### Don't
55
+
56
+ ```toml
57
+ # .codelaw/deps-snapshot.json
58
+ { "fetched": "2026-10-25", "packages": [ }
59
+ # pyproject.toml
60
+ [project]
61
+ name = "app"
62
+ ```
63
+
64
+ #### Do
65
+
66
+ ```toml
67
+ # .codelaw/deps-snapshot.json
68
+ { "fetched": "2026-10-25", "packages": {} }
69
+ # pyproject.toml
70
+ [project]
71
+ name = "app"
72
+ ```
@@ -0,0 +1,140 @@
1
+ ---
2
+ id: deps/vulnerable
3
+ title: "No dependency in use has a known vulnerability"
4
+ languages: [json, toml]
5
+ files: ["**/package.json", "**/pyproject.toml"]
6
+ fix: suggest
7
+ fix_reason: "the fix moves a range or adds an override to the lowest known-clean version, which changes what installs; a new major can change behaviour, and an override changes the install of the whole tree"
8
+ stability: preview
9
+ since: 0.5.0
10
+ ---
11
+
12
+ Every version a project installs — each dependency of a `package.json` or `pyproject.toml`, and every package its lockfile (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `uv.lock`, `poetry.lock`) installs through them — is compared with the advisories in `.codelaw/deps-snapshot.json`, which `codelaw deps refresh` wrote from the enabled `[deps] advisory_sources`. The rule reads only that file and the lockfiles; it never reads the network, so `check` gives the same answer offline. With no snapshot, or one that holds no advisories, nothing is reported (`deps/incomplete-scan` says why).
13
+
14
+ The finding names the worst advisory, its severity and CVE, how many more there are, and the version to move to: the **lowest known-clean** version above the one in use — a version no merged advisory affects and an advisory source covered — that is not deprecated or yanked and is at least `[deps] min_release_age` old, **inside the major in use first**. When the major has none, the lowest clean version above it is offered and the message says it is a new major. A fixed version no source covered is named but never offered ("not verified clean"); with no fixed version at all, the fix is manual.
15
+
16
+ Each finding is graded by its worst advisory, and `[deps] severity` sets each grade's severity (or `off`):
17
+
18
+ | advisory severity | default |
19
+ |---|---|
20
+ | `critical`, `high` | `error` |
21
+ | `moderate` | `warn` |
22
+ | `low` | `info` |
23
+
24
+ An advisory no source grades counts as `high`.
25
+
26
+ Where it is reported, and the fix:
27
+
28
+ - **A direct dependency:** on its line in the manifest; the fix moves the range's version to the target and keeps its operator (`^`, `~`, `>=`, `=` or none; `==`, `>=` or `~=`).
29
+ - **A transitive one:** on the first line of the manifest beside the lockfile — where the override that fixes it is written — and the fix adds that override at the exact target: npm `overrides`, `pnpm.overrides`, yarn `resolutions`, uv's `[tool.uv] override-dependencies`. A lockfile is never edited. An override already in the manifest is the version the next install takes: a clean one settles the finding, a vulnerable one is reported with the version to change it to. A yarn classic finding has a copy on its `yarn.lock` entry.
30
+ - **In `poetry.lock`:** Poetry has no override, so the message says to add a direct constraint.
31
+
32
+ Every message ends with the install to run (`npm install`, `uv lock`, …) and the snapshot's day, and says `incomplete` while an enabled source was unavailable. `[deps] ignore` takes a package, or `{ package, advisory, expires, added_by, reason }` for one advisory until a date.
33
+
34
+ **Why:** A vulnerable version stays exploitable until someone moves it, and the version that fixes one advisory can carry another; the lowest version every source leaves clean is the smallest safe change.
35
+
36
+ ```codelaw
37
+ native: deps/vulnerable
38
+ ```
39
+
40
+ ## How to fix
41
+
42
+ 1. Run `codelaw fix --unsafe` to move the range (or add the override) to the version named, or make the same edit by hand.
43
+ 2. Run the install the message names (`npm install`, `pnpm install`, `yarn install`, `uv lock`, `poetry lock`) so the lockfile follows; codelaw never runs installers.
44
+ 3. For a new major, read the package's changelog and update the code that uses it.
45
+ 4. With no clean version: replace the package, remove it, or add a dated `[deps] ignore` entry naming the advisory, with a reason.
46
+
47
+ ## Examples
48
+
49
+ ### JSON
50
+
51
+ #### Don't
52
+
53
+ ```json
54
+ // .codelaw/deps-snapshot.json
55
+ {
56
+ "fetched": "2026-10-29",
57
+ "packages": {
58
+ "npm:lodash": {
59
+ "versions": { "4.17.15": "2019-07-19", "4.17.21": "2021-02-20" },
60
+ "advisories": [ { "id": "GHSA-35jh-r3h4-6jhm", "aliases": ["CVE-2021-23337"], "severity": "high", "affected": ["<4.17.21"], "fixed": ["4.17.21"], "sources": ["osv"] } ],
61
+ "scanned": { "osv": ["*"] }
62
+ }
63
+ },
64
+ "sources": { "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" } }
65
+ }
66
+ // package.json
67
+ {
68
+ "dependencies": {
69
+ "lodash": "^4.17.15"
70
+ }
71
+ }
72
+ ```
73
+
74
+ #### Do
75
+
76
+ ```json
77
+ // .codelaw/deps-snapshot.json
78
+ {
79
+ "fetched": "2026-10-29",
80
+ "packages": {
81
+ "npm:lodash": {
82
+ "versions": { "4.17.15": "2019-07-19", "4.17.21": "2021-02-20" },
83
+ "advisories": [ { "id": "GHSA-35jh-r3h4-6jhm", "aliases": ["CVE-2021-23337"], "severity": "high", "affected": ["<4.17.21"], "fixed": ["4.17.21"], "sources": ["osv"] } ],
84
+ "scanned": { "osv": ["*"] }
85
+ }
86
+ },
87
+ "sources": { "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" } }
88
+ }
89
+ // package.json
90
+ {
91
+ "dependencies": {
92
+ "lodash": "^4.17.21"
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### TOML
98
+
99
+ #### Don't
100
+
101
+ ```toml
102
+ # .codelaw/deps-snapshot.json
103
+ {
104
+ "fetched": "2026-10-29",
105
+ "packages": {
106
+ "pypi:jinja2": {
107
+ "versions": { "3.1.2": "2022-04-28", "3.1.3": "2024-01-10" },
108
+ "advisories": [ { "id": "GHSA-h5c8-rqwp-cp95", "severity": "moderate", "affected": ["<3.1.3"], "fixed": ["3.1.3"], "sources": ["osv"] } ],
109
+ "scanned": { "osv": ["*"] }
110
+ }
111
+ },
112
+ "sources": { "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" } }
113
+ }
114
+ # pyproject.toml
115
+ [project]
116
+ name = "app"
117
+ dependencies = ["jinja2>=3.1.2"]
118
+ ```
119
+
120
+ #### Do
121
+
122
+ ```toml
123
+ # .codelaw/deps-snapshot.json
124
+ {
125
+ "fetched": "2026-10-29",
126
+ "packages": {
127
+ "pypi:jinja2": {
128
+ "versions": { "3.1.2": "2022-04-28", "3.1.3": "2024-01-10" },
129
+ "advisories": [ { "id": "GHSA-h5c8-rqwp-cp95", "severity": "moderate", "affected": ["<3.1.3"], "fixed": ["3.1.3"], "sources": ["osv"] } ],
130
+ "scanned": { "osv": ["*"] }
131
+ }
132
+ },
133
+ "sources": { "osv": { "kind": "osv", "state": "ok", "on": "2026-10-29" } }
134
+ }
135
+ # pyproject.toml
136
+ [project]
137
+ name = "app"
138
+ dependencies = ["jinja2>=3.1.3"]
139
+ ```
140
+
@@ -0,0 +1,74 @@
1
+ Metadata-Version: 2.4
2
+ Name: codelaw-rules-deps
3
+ Version: 0.4.2
4
+ Summary: codelaw's dependency rules: vulnerable packages and the version to move to, latest versions, the snapshot they read (SR-RULE-PACKS)
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Project-URL: Repository, https://github.com/arpitarya/codelaw
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+
11
+ # @codelaw/rules-deps
12
+
13
+ codelaw's dependency rules — one of the first-party rule packs
14
+ ([SR-RULE-PACKS](../../records/0101_rule-packs.md) decision 15), on npm and
15
+ PyPI (`codelaw-rules-deps`). It tells you, and your coding agent, which npm
16
+ and Python dependencies are vulnerable and the exact version to move to, and
17
+ which are behind their latest release.
18
+
19
+ `codelaw init` adds it when the repo has a `package.json` or `pyproject.toml`.
20
+
21
+ ```toml
22
+ # codelaw.toml
23
+ extends = ["codelaw:deps/recommended"]
24
+ preview = true # every rule is `preview` until a corpus run promotes it
25
+ ```
26
+
27
+ ```sh
28
+ npm i -D @codelaw/rules-deps # or
29
+ pip install codelaw-rules-deps
30
+ codelaw deps refresh # the one command that reads the network
31
+ ```
32
+
33
+ ## Presets
34
+
35
+ <!-- docs-sync:presets -->
36
+
37
+ | preset | rules | what it holds |
38
+ |---|---|---|
39
+ | `deps/recommended` | 4 | Vulnerable and outdated dependencies of package.json and pyproject.toml, from the committed snapshot `codelaw deps refresh` writes |
40
+
41
+ <!-- /docs-sync:presets -->
42
+
43
+ ## Rules
44
+
45
+
46
+
47
+ | rule | fix | what it reports |
48
+ |---|---|---|
49
+ | `deps/vulnerable` | suggest (manual with no clean version) | a version in use, direct or transitive, that an advisory affects, with the lowest known-clean version to move to |
50
+ | `deps/incomplete-scan` | manual | an enabled advisory source the last refresh could not read |
51
+ | `deps/outdated` | suggest | a dependency behind its latest version, or a deprecated or yanked one (was `data/outdated-dependency`) |
52
+ | `deps/stale-snapshot` | manual | a snapshot older than `[deps] max_snapshot_age`, or one that cannot be read (was `data/stale-deps-snapshot`) |
53
+
54
+
55
+
56
+ ## How it works
57
+
58
+ The rules read `.codelaw/deps-snapshot.json`, which `codelaw deps refresh`
59
+ writes and the project commits, and the lockfiles — never the network, so
60
+ `codelaw check` gives the same answer offline and in CI.
61
+
62
+ - **Advisory sources** are `[deps] advisory_sources`, each on or off:
63
+ `registry` (the npm registry and Python index you already install from)
64
+ first, then `osv` (`https://api.osv.dev`), or a mirror of either. Every
65
+ enabled source is read and merged — the safer answer wins. A source that
66
+ cannot be read is recorded, and `deps/incomplete-scan` says so.
67
+ - **The version to move to** is the lowest version every advisory leaves
68
+ clean and some source actually covered, inside the major in use first.
69
+ - **Agents** ask `check_dependency` (MCP) or `codelaw deps check` before
70
+ adding a package; `[deps] agent` sets, per severity, whether the hooks
71
+ only inform or also block.
72
+
73
+ The pack holds no advisory data: the snapshot keeps ids, ranges, versions, a
74
+ severity, a URL and the sources' names — never an advisory's text.
@@ -0,0 +1,14 @@
1
+ codelaw_rules_deps/LICENSE,sha256=_R8NFLyGiKUo7mPzbUGbqg3hdEKYhaTsIgBGXqtFfa8,1097
2
+ codelaw_rules_deps/NOTICE,sha256=up80-gF4yoOW-dq9YbF8ZKWRl4dwRe7cOpGqnA5YsTk,554
3
+ codelaw_rules_deps/README.md,sha256=5o_x0O6JshrBNwOmSaD3idG92-3a8UzyhmsfOEHl5IM,2686
4
+ codelaw_rules_deps/codelaw-pack.toml,sha256=12rT1gBEC8cHdCZc04QTNbKMKM7tavCRm1fxpBQpzsk,285
5
+ codelaw_rules_deps/corpus.toml,sha256=kmwZ7alsRvvMx7wPamEupJKsnD1nVooO1XzwYanOGR8,237
6
+ codelaw_rules_deps/presets/deps/recommended.toml,sha256=ZaBUabTWQpRUeZnaInI7F9vxsTkNrTFpsBptoYVM5EA,272
7
+ codelaw_rules_deps/rules/deps/incomplete-scan.md,sha256=_RXsYzN4YlmzuQlnus58ds80iDrAa0X0naA5cstHrQ4,2594
8
+ codelaw_rules_deps/rules/deps/outdated.md,sha256=foCpPwk0tFdX57mOCADONkVr1hoFmN8-PRSRrOMTBqk,3775
9
+ codelaw_rules_deps/rules/deps/stale-snapshot.md,sha256=zHho8ro3Hj7CkLVosa2-XR9AezxAjt2LLKlhA0mqtR4,1764
10
+ codelaw_rules_deps/rules/deps/vulnerable.md,sha256=rkbKpvD_z_Envz87oNC3P2I713aj9_-3B8o7YkWMA4M,5997
11
+ codelaw_rules_deps-0.4.2.dist-info/METADATA,sha256=cl0cCxsFrlHOwriry3fxrJ7IXBvvr9lLQtLsMpfbytA,3062
12
+ codelaw_rules_deps-0.4.2.dist-info/WHEEL,sha256=iL940CG79gUG1gJG0fuOXtdNe75u1bVsFzkAeObStpM,97
13
+ codelaw_rules_deps-0.4.2.dist-info/licenses/LICENSE,sha256=_R8NFLyGiKUo7mPzbUGbqg3hdEKYhaTsIgBGXqtFfa8,1097
14
+ codelaw_rules_deps-0.4.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: codelaw scripts/package.py
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Arpit Arya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ SPDX-License-Identifier: MIT