# dependency-auditor — heuristic software-composition analysis

Dependency & supply-chain audit pack for JavaScript/Node package.json manifests: parse dependencies/devDependencies/peer/optional into a normalized list, flag semver-range risk from outdated/loose...


Static audit of a Node/JS `package.json`: parse dependencies, score semver-range risk, bucket
licenses, raise severity flags, count by type, and advise deduping. Pure ESM, Node built-ins only,
zero npm deps. **No live npm registry or CVE feed** — every signal is a deterministic heuristic over
the manifest text, so it works fully offline.

## Tools

| Tool | Input | Output |
|---|---|---|
| `parse` | `{ packageJson }` or `{ deps }` | Normalized dep list `{ name, range, type, scope, specifier, preMajor, version }` + counts by type. |
| `outdatedHeuristic` | `{ packageJson }` / `{ deps }` | Range-tightness risk per dep (wildcard/tag/git → high, caret/tilde → low), a health score/grade. |
| `licenseSummary` | `{ licenses }` or `{ packageJson }` | Licenses bucketed permissive / weak-copyleft / copyleft / network-copyleft / proprietary / unknown, strongest obligation, risky packages. |
| `severityFlags` | `{ packageJson }` / `{ deps }` | Named flags: unpinned-range, git-dependency, prerelease-lock, caret-pre-1.0, deprecated-name-heuristic, too-many-deps. |
| `countByType` | `{ packageJson }` / `{ deps }` | Counts by type, specifier kind, and scope. |
| `dedupeAdvice` | `{ packageJson }` / `{ deps }` | Duplicate declarations, `@types` in prod, and overlapping-library clusters (moment vs dayjs, request vs axios…). |

## Usage

```js
import pack from './index.js';
const pkg = { dependencies: { react: '^18.2.0', moment: '*', 'left-pad': '1.0.0' }, devDependencies: { jest: '^29' } };
const risk = await pack.adapters.outdatedHeuristic({ packageJson: pkg });
// risk.highRisk -> ['moment'] ; risk.grade -> e.g. 'C'
const lic = pack.adapters.licenseSummary({ licenses: { react: 'MIT', ffmpeg: 'GPL-3.0', srv: 'AGPL-3.0' } });
// lic.strongestObligation -> 'network-copyleft'
```

## AI mode

`outdatedHeuristic` accepts `options.ai: true`; when a model is reachable (`../_shared/llm.js`) it
adds a plain-English `narrative` and is tagged `mode: 'llm'`. Otherwise you get the deterministic
analysis tagged `mode: 'heuristic'`. A down model never throws.

## DRY boundary

Audits JS `package.json` manifest text with heuristics. It does **not** hit the npm registry, resolve
a full lockfile tree, or fetch real CVEs. Dockerfile/container analysis lives in `dockerfile`;
webhook signing/verification lives in `webhook-forge`.


---
Source: shared/engines/adapters/domain/dependency-auditor/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/dependency-auditor
