dennisdoomen / dennisdoomen/packageguard

[Feature]: Add a `packageguard explain <package>` command showing dependency paths and verdict rationale

Closed
#223 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
C#
Stars
73
Forks
3
Avg merge
3h
Merged PRs (30d)
20

Description

### Background and motivation

When a build fails on a transitive package, the developer's first two questions are "what is this?" and "why is it in my project?" — and neither is answered by the current output. There is an existing roadmap item for displaying the reason a package was flagged; this proposes going further and making it explorable on demand.

The most frustrating case is a violation on a package the developer has never heard of, pulled in three levels down by something else. Without the dependency path, there is no way to know what to do about it.

**Proposal**

```bash
packageguard explain Newtonsoft.Json
```

```
Newtonsoft.Json 13.0.3
License: MIT (from package metadata)
Feed: nuget.org
Status: ALLOWED (matches allow list entry "MIT")

Required by:
MyApp.Web
-> Microsoft.AspNetCore.Mvc.NewtonsoftJson 8.0.0
-> Newtonsoft.Json 13.0.3
MyApp.Domain
-> Newtonsoft.Json 13.0.3 (direct)

Version resolution:
MyApp.Domain requested [12.0.0, ) -> resolved to 13.0.3
Microsoft.AspNetCore.Mvc.NewtonsoftJson requested [13.0.3, ) -> resolved to 13.0.3

Risk: 22.4 (low)
Legal 1.0 MIT, permissive, license URL valid
Security 2.1 No known vulnerabilities; signed by verified publisher
Operational 3.8 Actively maintained; 2 releases in the last 12 months
```

Design points:

- **The dependency path is the most valuable part.** It converts "some package I have never heard of is blocking my build" into "upgrade or replace this one direct dependency". The lock file already contains the graph, so the data is present.
- **Version resolution detail** explains why a version different from the one requested was selected — a recurring source of confusion in NuGet.
- **Risk factor breakdown** is already computed as `RiskFactorContribution` with rationale text; this simply surfaces it per package on demand rather than only in the HTML report.
- **Explain the verdict, not just the state.** Naming the specific policy rule that allowed or denied the package, and which configuration file it came from, is essential once hierarchical configs and presets are in play.
- **Fuzzy name matching.** Accepting a partial or case-insensitive name and suggesting candidates avoids forcing exact typing of long package identifiers.
- **Reuse the cache.** With `--use-caching` this should be near-instant, which is what makes it something people actually use interactively.

A companion `--why` on a violation in the normal output, showing an abbreviated path inline, would cover the common case without a second command.

### Alternative Concerns

- `dotnet nuget why` covers the dependency path for NuGet, but does not know about policy or risk, and does not cover the npm side.
- Putting all of this in the default output would make it unreadable; on-demand is the right shape.

### Are you willing help with a pull-request?

No

Contributor guide

Open the contributing guide

Research direction

Start at the proposed `packageguard explain ` entry point and inspect how the lock file exposes dependency graphs, how `RiskFactorContribution` stores rationale, and how verdict and cache data are currently produced. Done means an on-demand explanation can show dependency paths, version resolution, risk factors, policy rationale, fuzzy matches, and cached results; the payload names no files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.