{
  "schema": "leumas.docs.page/1",
  "id": "adapter:domain/dependency-auditor",
  "slug": "adapters/domain/dependency-auditor",
  "kind": "capabilities",
  "bucket": "package",
  "title": "dependency-auditor — heuristic software-composition analysis",
  "name": "dependency-auditor",
  "eyebrow": "heuristic software-composition analysis",
  "chip": null,
  "summary": "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...",
  "keywords": [
    "dependency-auditor",
    "devdependencies",
    "semver-range",
    "outdated",
    "caret",
    "tilde",
    "permissive",
    "weak-copyleft"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# dependency-auditor — heuristic software-composition analysis\n\nStatic audit of a Node/JS `package.json`: parse dependencies, score semver-range risk, bucket\nlicenses, raise severity flags, count by type, and advise deduping. Pure ESM, Node built-ins only,\nzero npm deps. **No live npm registry or CVE feed** — every signal is a deterministic heuristic over\nthe manifest text, so it works fully offline.\n\n## Tools\n\n| Tool | Input | Output |\n|---|---|---|\n| `parse` | `{ packageJson }` or `{ deps }` | Normalized dep list `{ name, range, type, scope, specifier, preMajor, version }` + counts by type. |\n| `outdatedHeuristic` | `{ packageJson }` / `{ deps }` | Range-tightness risk per dep (wildcard/tag/git → high, caret/tilde → low), a health score/grade. |\n| `licenseSummary` | `{ licenses }` or `{ packageJson }` | Licenses bucketed permissive / weak-copyleft / copyleft / network-copyleft / proprietary / unknown, strongest obligation, risky packages. |\n| `severityFlags` | `{ packageJson }` / `{ deps }` | Named flags: unpinned-range, git-dependency, prerelease-lock, caret-pre-1.0, deprecated-name-heuristic, too-many-deps. |\n| `countByType` | `{ packageJson }` / `{ deps }` | Counts by type, specifier kind, and scope. |\n| `dedupeAdvice` | `{ packageJson }` / `{ deps }` | Duplicate declarations, `@types` in prod, and overlapping-library clusters (moment vs dayjs, request vs axios…). |\n\n## Usage\n\n```js\nimport pack from './index.js';\nconst pkg = { dependencies: { react: '^18.2.0', moment: '*', 'left-pad': '1.0.0' }, devDependencies: { jest: '^29' } };\nconst risk = await pack.adapters.outdatedHeuristic({ packageJson: pkg });\n// risk.highRisk -> ['moment'] ; risk.grade -> e.g. 'C'\nconst lic = pack.adapters.licenseSummary({ licenses: { react: 'MIT', ffmpeg: 'GPL-3.0', srv: 'AGPL-3.0' } });\n// lic.strongestObligation -> 'network-copyleft'\n```\n\n## AI mode\n\n`outdatedHeuristic` accepts `options.ai: true`; when a model is reachable (`../_shared/llm.js`) it\nadds a plain-English `narrative` and is tagged `mode: 'llm'`. Otherwise you get the deterministic\nanalysis tagged `mode: 'heuristic'`. A down model never throws.\n\n## DRY boundary\n\nAudits JS `package.json` manifest text with heuristics. It does **not** hit the npm registry, resolve\na full lockfile tree, or fetch real CVEs. Dockerfile/container analysis lives in `dockerfile`;\nwebhook signing/verification lives in `webhook-forge`.\n",
  "source": {
    "path": "shared/engines/adapters/domain/dependency-auditor/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 2611,
    "hash": "eb1b49bd0460acbf6c0670f50071cb1550cd626b"
  },
  "urls": {
    "html": "/p/adapters/domain/dependency-auditor",
    "json": "/docs/adapters/domain/dependency-auditor.json",
    "md": "/docs/adapters/domain/dependency-auditor.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
