# Dependency & Supply-Chain Audit

Reports what a project actually depends on, what of that its code actually reaches, and which findings therefore matter first.

## Deliverable

One Markdown document, `dependency-risk-report.md`, in the structure set out under **Output** below. It receives the dependencies named by **Security Review of a Change** and returns the risk each one carries.

## Required inputs

- **The dependency manifest and its lockfile** — both. A manifest states intent; the lockfile states what is installed.
- **The application code** — so a dependency can be traced to the paths that reach it, or shown to be reached by none.
- **The advisory source you may consult**, and the date of its data. This skill copies advisories from a source; it never recalls them.

If any is absent, report it as missing before auditing. Never state an advisory identifier, an affected range or a version from memory — an advisory quoted from recollection is indistinguishable from an invented one.

## Optional inputs

- The build and deployment configuration, including whatever runs at install time
- The licence policy the project has to satisfy
- Previous audits, and the decisions taken on what they found
- Which dependencies are pinned by policy and which are allowed to float
- Registry and mirror configuration, and whether artefacts are verified on download
- The list of dependencies added by the change currently under review

Where an optional input is absent, the section that depends on it reports `not assessed` with the reason. It never reports `clean`.

## Execution

**1 — Resolve the real tree.** From the lockfile, list the direct dependencies and everything they pull in, with the resolved version of each. Record the depth of each transitive dependency and the path by which it arrived. A tree read from the manifest instead of the lockfile is a different tree, and the report states which one it read.

**2 — Separate reachable from merely installed.** For each dependency, establish whether any path in the application reaches it, and record `reached`, `not reached` or `undetermined` with how that was established. Most of a tree is usually not reached; treating all of it as live buries the part that runs.

**3 — Check each dependency against the advisory source you were given.** Record the source and the date of its data. Copy every identifier and affected range from it, and compare against the installed version. A dependency the source does not cover is recorded `not covered`, which is not the same as safe.

**4 — Read the maintenance signals.** Per direct dependency: when it last changed, how many people can publish a release, whether the published artefact corresponds to a public source tree, and whether it is archived or deprecated. Record each signal with where it was read and when.

**5 — Record the licence obligations.** Per dependency: the declared licence, whether the way this project distributes its software triggers an obligation, and any dependency whose licence could not be determined. A licence taken from package metadata rather than from the licence file is marked as such.

**6 — Find what executes at install and build time.** Install hooks, post-install scripts, code generation, binaries fetched while building, and anything that reaches the network during packaging. This code runs on developer machines and build agents with their privileges, so it is audited as running code rather than as metadata.

**7 — Order the findings by reachability.** Group them into reached code, build-time only, and not reached, and state which group each finding is in. Within a group, order by impact. The report never presents an advisory against code no path reaches as equivalent to one on a path that runs on every request.

## Output

`dependency-risk-report.md`, in this order:

- **1. Scope and date** — which manifest and lockfile were read, which advisory source and the date of its data, and when
- **2. Dependency tree** — direct dependencies with resolved versions, and the transitive count and depth behind each
- **3. Reachability** — per dependency: `reached`, `not reached` or `undetermined`, and how that was established
- **4. Advisory findings** — per finding: the dependency, the identifier as the source gives it, the affected range, the installed version, the reachability group
- **5. Maintenance signals** — per direct dependency: last change, who can publish, source correspondence, status
- **6. Licences** — per dependency: the declared licence, the obligation it triggers, or `undetermined`
- **7. Install-time and build-time execution** — what runs, from which package, and with what access
- **8. Pinning and verification** — what is pinned, what floats, and whether artefacts are verified on install
- **9. Not determined** — what could not be established, why, and what would establish it

## Validation

The report is ready when all of these hold:

- Every direct dependency in section 2 appears in sections 3, 5 and 6
- Every finding in section 4 names the source it was copied from and its reachability group
- No identifier, affected range or version appears that did not come from the supplied source
- Every dependency in section 3 carries one of the three reachability values, with none left blank
- Sections 5 and 6 read `undetermined` where the material did not settle them, never `none`
- Section 9 is either non-empty or states that everything in scope was determined

Fail the run if an advisory identifier or a version appears without the source it was read from, or if a dependency is reported as safe on the grounds that nothing was found.

## Failure handling

- **No lockfile** — audit the manifest, mark every version `as declared, not as installed`, and report that the reachability and advisory results describe a tree that may not be the deployed one.
- **No advisory source available** — produce every other section and mark section 4 `not assessed — no advisory source supplied`. Never fill it from memory.
- **Reachability cannot be determined** — mark the dependency `undetermined`, order it as though it were reached, and state in section 9 which findings that affects.
- **The manifest and the lockfile disagree** — record both, audit the lockfile, and raise the disagreement in section 9 as blocking. A project that installs something other than what it declares has a second problem behind the first.
- **Several ecosystems in one project** — audit each manifest separately and report them separately, listing any directory not covered in section 9. A single merged list hides which package manager installs what.
