Make every scan repeatable.
Store PackageMedic policy beside the code so local runs and CI evaluate the same rules, severities, exclusions, and operational limits.
Create the configuration
package-medic initThe CLI searches for .packagemedic.json from the selected target toward the repository root. Use --config for a different file or --no-configto disable discovery. CLI values win over configuration, which wins over safe defaults.
Complete example
{
"$schema": "https://raw.githubusercontent.com/GonzMeza/package-medic/main/schemas/packagemedic.schema.json",
"schemaVersion": 1,
"failOn": "none",
"failOnNew": "warning",
"baseline": ".packagemedic-baseline.json",
"maxParallelism": 4,
"exclude": ["**/bin/**", "**/obj/**"],
"rules": {
"PM006": { "enabled": true, "severity": "warning" },
"PM007": { "enabled": true, "severity": "error" },
"PM008": { "enabled": true, "severity": "warning" }
},
"suppressions": [
{
"rule": "PM003",
"path": "src/Legacy/**",
"package": "Example.Legacy",
"reason": "Intentional exception tracked in issue 42"
}
],
"impact": {
"failOnDowngrade": true,
"failOnDirectToTransitive": true,
"maxAddedPackages": 40,
"maxAddedTransitivePackages": 25,
"failOnSourceChange": true,
"failOnContentChange": true,
"requirePackageSourceMapping": true,
"requireLockedMode": true,
"allowedSources": ["https://api.nuget.org/v3/index.json"]
},
"timeouts": {
"restoreSeconds": 300,
"evaluationSeconds": 60
}
}Configuration properties
| Property | Accepted value | Purpose |
|---|---|---|
schemaVersion | 1 | Required configuration contract version; independent of the product version. |
failOn | none, warning, error | Default threshold for all effective findings. |
failOnNew | none, warning, error | Default threshold for findings absent from a baseline. |
baseline | Relative path | Baseline resolved relative to this configuration file. |
exclude | Glob array | Portable repository paths that should not be analyzed. |
rules | PM001–PM008 map | Enable a rule and optionally override its severity. |
suppressions | Rule selectors | Document intentional exceptions by path and/or exact package. |
impact | Impact Gate object | Set dependency growth, downgrade, source-trust, source-mapping, and locked-restore policy for diff. |
maxParallelism | 1–32 | Maximum concurrent restore, audit, and MSBuild processes. |
timeouts | 1–3600 seconds | Bound restore and per-project evaluation. |
Impact policy is a separate gate
The impact object applies to complete Git comparisons. Downgrades, direct-to-transitive transitions, source changes, and loss/gain of source evidence fail by default. Package growth budgets, an allowlist, Package Source Mapping, and locked restore are opt-in so teams can adopt them deliberately. A SHA-512 content change under the same package ID/version identity is rejected by default because it deserves explicit supply-chain review.
Allowed sources must be credential-free HTTPS URLs; local is supported only as an explicit value. With an active allowlist, unknown source metadata fails closed. Impact violations are not diagnostic suppressions: change the policy through review when the repository boundary genuinely changes.
Suppress intentionally, not invisibly
Every suppression requires a non-empty reason. A selector always names one rule and may narrow the match with a repository-relative path glob, an exact package ID, or both. Suppressed findings do not reach failure gates, but remain counted in report policy metadata and retain their reason in detailed text and JSON.
Fail-closed input boundaries
Configuration is bounded to 1 MiB, 1,000 exclusions, 1,000 suppressions, and 4,096 characters per glob. Invalid, oversized, unknown, or mistyped properties cause exit code2; PackageMedic never silently continues with partial policy.