eslint-plugin-traceability 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/README.md +73 -32
  3. package/docs/ci-cd-pipeline.md +224 -0
  4. package/docs/cli-integration.md +22 -0
  5. package/docs/code-quality-refactor-opportunities-2025-12-03.md +78 -0
  6. package/docs/config-presets.md +38 -0
  7. package/docs/conventional-commits-guide.md +185 -0
  8. package/docs/custom-rules-development-guide.md +659 -0
  9. package/docs/decisions/0001-allow-dynamic-require-for-built-plugins.md +26 -0
  10. package/docs/decisions/001-typescript-for-eslint-plugin.accepted.md +111 -0
  11. package/docs/decisions/002-jest-for-eslint-testing.accepted.md +137 -0
  12. package/docs/decisions/003-code-quality-ratcheting-plan.md +48 -0
  13. package/docs/decisions/004-automated-version-bumping-for-ci-cd.md +196 -0
  14. package/docs/decisions/005-github-actions-validation-tooling.accepted.md +144 -0
  15. package/docs/decisions/006-semantic-release-for-automated-publishing.accepted.md +227 -0
  16. package/docs/decisions/007-github-releases-over-changelog.accepted.md +216 -0
  17. package/docs/decisions/008-ci-audit-flags.accepted.md +60 -0
  18. package/docs/decisions/009-security-focused-lint-rules.accepted.md +64 -0
  19. package/docs/decisions/010-implements-annotation-for-multi-story-requirements.proposed.md +184 -0
  20. package/docs/decisions/adr-0001-console-usage-for-cli-guards.md +190 -0
  21. package/docs/decisions/adr-accept-dev-dep-risk-glob.md +40 -0
  22. package/docs/decisions/adr-commit-branch-tests.md +54 -0
  23. package/docs/decisions/adr-maintenance-cli-interface.md +140 -0
  24. package/docs/decisions/adr-pre-push-parity.md +112 -0
  25. package/docs/decisions/code-quality-ratcheting-plan.md +53 -0
  26. package/docs/dependency-health.md +238 -0
  27. package/docs/eslint-9-setup-guide.md +517 -0
  28. package/docs/eslint-plugin-development-guide.md +487 -0
  29. package/docs/functionality-coverage-2025-12-03.md +250 -0
  30. package/docs/jest-testing-guide.md +100 -0
  31. package/docs/rules/prefer-implements-annotation.md +219 -0
  32. package/docs/rules/require-branch-annotation.md +71 -0
  33. package/docs/rules/require-req-annotation.md +203 -0
  34. package/docs/rules/require-story-annotation.md +159 -0
  35. package/docs/rules/valid-annotation-format.md +418 -0
  36. package/docs/rules/valid-req-reference.md +153 -0
  37. package/docs/rules/valid-story-reference.md +120 -0
  38. package/docs/security-incidents/2025-11-17-glob-cli-incident.md +45 -0
  39. package/docs/security-incidents/2025-11-18-brace-expansion-redos.md +45 -0
  40. package/docs/security-incidents/2025-11-18-bundled-dev-deps-accepted-risk.md +93 -0
  41. package/docs/security-incidents/2025-11-18-tar-race-condition.md +43 -0
  42. package/docs/security-incidents/2025-12-03-dependency-health-review.md +58 -0
  43. package/docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md +104 -0
  44. package/docs/security-incidents/SECURITY-INCIDENT-TEMPLATE.md +37 -0
  45. package/docs/security-incidents/dependency-override-rationale.md +57 -0
  46. package/docs/security-incidents/dev-deps-high.json +116 -0
  47. package/docs/security-incidents/handling-procedure.md +54 -0
  48. package/docs/stories/001.0-DEV-PLUGIN-SETUP.story.md +92 -0
  49. package/docs/stories/002.0-DEV-ESLINT-CONFIG.story.md +82 -0
  50. package/docs/stories/003.0-DEV-FUNCTION-ANNOTATIONS.story.md +112 -0
  51. package/docs/stories/004.0-DEV-BRANCH-ANNOTATIONS.story.md +153 -0
  52. package/docs/stories/005.0-DEV-ANNOTATION-VALIDATION.story.md +138 -0
  53. package/docs/stories/006.0-DEV-FILE-VALIDATION.story.md +144 -0
  54. package/docs/stories/007.0-DEV-ERROR-REPORTING.story.md +163 -0
  55. package/docs/stories/008.0-DEV-AUTO-FIX.story.md +150 -0
  56. package/docs/stories/009.0-DEV-MAINTENANCE-TOOLS.story.md +117 -0
  57. package/docs/stories/010.0-DEV-DEEP-VALIDATION.story.md +124 -0
  58. package/docs/stories/010.1-DEV-CONFIGURABLE-PATTERNS.story.md +149 -0
  59. package/docs/stories/010.2-DEV-MULTI-STORY-SUPPORT.story.md +216 -0
  60. package/docs/stories/010.3-DEV-MIGRATE-TO-IMPLEMENTS.story.md +236 -0
  61. package/docs/stories/developer-story.map.md +120 -0
  62. package/docs/ts-jest-presets-guide.md +548 -0
  63. package/lib/src/index.d.ts +2 -2
  64. package/lib/src/index.js +2 -0
  65. package/lib/src/maintenance/batch.d.ts +5 -0
  66. package/lib/src/maintenance/batch.js +5 -0
  67. package/lib/src/maintenance/cli.js +34 -212
  68. package/lib/src/maintenance/commands.d.ts +32 -0
  69. package/lib/src/maintenance/commands.js +139 -0
  70. package/lib/src/maintenance/detect.d.ts +2 -0
  71. package/lib/src/maintenance/detect.js +4 -0
  72. package/lib/src/maintenance/flags.d.ts +99 -0
  73. package/lib/src/maintenance/flags.js +121 -0
  74. package/lib/src/maintenance/report.d.ts +2 -0
  75. package/lib/src/maintenance/report.js +2 -0
  76. package/lib/src/maintenance/update.d.ts +4 -0
  77. package/lib/src/maintenance/update.js +4 -0
  78. package/lib/src/rules/helpers/require-story-io.d.ts +3 -0
  79. package/lib/src/rules/helpers/require-story-io.js +20 -6
  80. package/lib/src/rules/helpers/valid-annotation-format-internal.d.ts +30 -0
  81. package/lib/src/rules/helpers/valid-annotation-format-internal.js +36 -0
  82. package/lib/src/rules/helpers/valid-annotation-options.js +15 -4
  83. package/lib/src/rules/helpers/valid-annotation-utils.js +5 -0
  84. package/lib/src/rules/helpers/valid-implements-utils.d.ts +75 -0
  85. package/lib/src/rules/helpers/valid-implements-utils.js +149 -0
  86. package/lib/src/rules/helpers/valid-story-reference-helpers.d.ts +3 -4
  87. package/lib/src/rules/prefer-implements-annotation.d.ts +39 -0
  88. package/lib/src/rules/prefer-implements-annotation.js +276 -0
  89. package/lib/src/rules/valid-annotation-format.js +87 -28
  90. package/lib/src/rules/valid-req-reference.js +71 -0
  91. package/lib/src/utils/reqAnnotationDetection.d.ts +4 -1
  92. package/lib/src/utils/reqAnnotationDetection.js +43 -15
  93. package/lib/tests/maintenance/cli.test.js +89 -0
  94. package/lib/tests/plugin-default-export-and-configs.test.js +3 -0
  95. package/lib/tests/rules/prefer-implements-annotation.test.d.ts +1 -0
  96. package/lib/tests/rules/prefer-implements-annotation.test.js +84 -0
  97. package/lib/tests/rules/require-req-annotation.test.js +8 -1
  98. package/lib/tests/rules/require-story-annotation.test.js +9 -4
  99. package/lib/tests/rules/valid-annotation-format.test.js +78 -0
  100. package/lib/tests/rules/valid-req-reference.test.js +34 -0
  101. package/lib/tests/utils/ts-language-options.d.ts +1 -7
  102. package/lib/tests/utils/ts-language-options.js +8 -5
  103. package/package.json +7 -3
  104. package/user-docs/api-reference.md +507 -0
  105. package/user-docs/eslint-9-setup-guide.md +639 -0
  106. package/user-docs/examples.md +74 -0
  107. package/user-docs/migration-guide.md +158 -0
@@ -0,0 +1,112 @@
1
+ # ADR: Pre-push vs CI parity for quality checks
2
+
3
+ Status: Accepted
4
+ Date: 2025-11-20
5
+
6
+ ## Context
7
+
8
+ The project has a comprehensive CI/CD pipeline (`.github/workflows/ci-cd.yml`) that runs on every push to `main` and on pull requests:
9
+
10
+ - `npm run build`
11
+ - `npm run type-check`
12
+ - `npm run lint`
13
+ - `npm run format:check`
14
+ - `npm run duplication`
15
+ - `npm run check:traceability`
16
+ - `npm test -- --coverage`
17
+ - `npm run audit:ci`
18
+ - `npm run safety:deps`
19
+ - `npm audit --production --audit-level=high`
20
+ - `npm run audit:dev-high`
21
+ - plus post-build checks such as `npm run lint-plugin-check` and a smoke test of the published package.
22
+
23
+ Locally, we previously used a fast subset of these checks (`ci-verify:fast`) as a pre-push safeguard to keep `main` healthy without making every push prohibitively slow. The existing `ci-verify` and `ci-verify:fast` scripts are:
24
+
25
+ ```jsonc
26
+ // package.json
27
+ "ci-verify": "npm run type-check && npm run lint && npm run format:check && npm run duplication && npm run check:traceability && npm test && npm run audit:ci && npm run safety:deps",
28
+ "ci-verify:fast": "npm run type-check && npm run check:traceability && npm run duplication && jest --ci --bail --passWithNoTests --testPathPatterns 'tests/(unit|fast)'"
29
+ ```
30
+
31
+ Running only the fast subset on every `git push` reduced local feedback times, but it also allowed a class of failures (lint, formatting, full test suite, audits) to be detected **only** in CI, leading to avoidable red pipelines and additional iteration overhead.
32
+
33
+ We now want **full parity** between local pre-push checks and the core CI quality checks, so that a successful push locally very strongly predicts CI success. A separate, optional fast-check path remains available for developers who want a quicker pre-flight before doing heavier work.
34
+
35
+ ## Decision
36
+
37
+ - The `.husky/pre-push` hook will run **`npm run ci-verify:full`**, a script that mirrors the **full CI-equivalent quality gate** (build, type-check, lint, formatting, duplication, traceability, full tests, and audits).
38
+ - We formally accept that pre-push checks are now a **comprehensive gate** focused on matching the CI quality bar, even at the cost of longer local push times.
39
+ - The previous fast-only `ci-verify:fast` remains available as an **optional, manual command** but is no longer wired into the pre-push hook.
40
+ - The **authoritative, complete gate** for `main` remains the CI/CD workflow on GitHub Actions, which may include additional CI-only post-build/post-publish steps.
41
+
42
+ Concretely, `.husky/pre-push` runs:
43
+
44
+ ```sh
45
+ npm run ci-verify:full && echo "Pre-push full CI-equivalent checks completed"
46
+ ```
47
+
48
+ and **does not** omit any of the core CI quality checks represented in `ci-verify:full`. The only remaining divergence is that certain CI-only steps (for example, publish-time smoke tests and release automation such as `semantic-release`) continue to run **only in CI**.
49
+
50
+ ## Rationale
51
+
52
+ - **Reduce CI-only failures**: The earlier approach (pre-push running only `ci-verify:fast`) led to recurring CI failures for checks not covered locally (lint, formatting, full tests, audits). Promoting a full CI-equivalent sequence to pre-push significantly lowers this risk.
53
+ - **Stronger local guarantees**: Developers can treat a successful push as a strong indicator that CI will also pass, improving confidence in trunk-based development and reducing context-switching caused by failed pipelines.
54
+ - **Explicit trade-off**: We accept longer pre-push times in exchange for fewer broken builds on `main` and fewer re-runs of CI for easily preventable issues.
55
+ - **Optional fast path preserved**: For workflows where rapid feedback is still important (e.g., early in a feature branch), `npm run ci-verify:fast` remains available as a manual pre-flight, but it is not the enforced gate.
56
+
57
+ ## Constraints and guardrails
58
+
59
+ To keep pre-push and CI aligned while retaining some flexibility, we adopt the following constraints:
60
+
61
+ 1. **Minimum checks in `ci-verify:full`**
62
+ - `ci-verify:full` (currently `ci-verify`) must remain the **full CI-equivalent quality sequence** runnable locally. At a minimum, it must include:
63
+ - `npm run build` (or equivalent build step, if present)
64
+ - `npm run type-check`
65
+ - `npm run lint`
66
+ - `npm run format:check`
67
+ - `npm run duplication`
68
+ - `npm run check:traceability`
69
+ - The main Jest test suite (including coverage configuration as enforced in CI)
70
+ - Security and dependency checks (`npm run audit:ci`, `npm run safety:deps`, and other CI-enforced audits)
71
+ - `.husky/pre-push` must invoke this full sequence (or its future renamed equivalent).
72
+ - `ci-verify:fast` is now a **manual, optional** helper for developers and is not the pre-push script.
73
+
74
+ 2. **Relationship to `ci-verify:full` and CI**
75
+ - `ci-verify:full` is the **script-level mirror** of the CI quality gates, intended to be as close as practical to what CI runs before any deploy/release steps.
76
+ - CI may include additional steps that are inherently CI-only (e.g., publish-time smoke tests, `lint-plugin-check` on the published artifact, release automation). These are not expected to run locally.
77
+ - `ci-verify:fast` is a secondary, **manual fast check** that can be used by contributors for quick feedback but does not replace `ci-verify:full` as the enforced pre-push gate.
78
+
79
+ 3. **Failure patterns and escalation**
80
+ - If CI frequently fails **despite** `ci-verify:full` being enforced pre-push (e.g., due to extremely slow or flaky steps, environment-specific issues, or CI-only checks beyond `ci-verify:full`):
81
+ - Maintain a log of which steps are responsible.
82
+ - Consider optimizing or parallelizing the slowest steps in `ci-verify:full`.
83
+ - As a last resort, consider **temporarily relaxing** the pre-push hook (for example, moving some especially slow but low-signal checks back to CI-only) while updating this ADR to describe the new contract.
84
+
85
+ 4. **Documentation linkage**
86
+ - `.husky/pre-push` and contributor docs must reference this ADR so maintainers and contributors can discover and understand the policy.
87
+ - Any changes to the composition of `ci-verify:full` or to which script `.husky/pre-push` invokes must be reflected here.
88
+
89
+ ## Rollback / migration plan
90
+
91
+ If we decide that pre-push parity with CI is too costly in practice (for example, due to repeatedly long pre-push times in common workflows), we can revert to the previous "fast subset" approach or a hybrid.
92
+
93
+ 1. **Option A – Roll back to fast-only pre-push (`ci-verify:fast`)**
94
+ - Change `.husky/pre-push` to run `npm run ci-verify:fast` instead of `ci-verify:full`.
95
+ - Explicitly document that pre-push is once again a **fast, partial gate**, and that contributors are encouraged to run `npm run ci-verify:full` manually before risky pushes.
96
+ - Update this ADR (or supersede it with a new one) to reflect the rollback and clearly describe which CI checks are no longer enforced pre-push.
97
+
98
+ 2. **Option B – Hybrid / optimized pre-push**
99
+ - If full parity is mostly helpful but certain steps are disproportionately slow or flaky, adjust `ci-verify:full` and the pre-push hook to:
100
+ - Keep the highest-value checks (type-check, lint, format, core tests, audits that commonly fail) in pre-push.
101
+ - Move only the least valuable or inherently CI-only steps back to CI.
102
+ - Document any deviation from full parity in this ADR, including which checks are pre-push vs CI-only.
103
+
104
+ 3. **Option C – Workflow-specific relaxation**
105
+ - For specific workflows (e.g., automated tooling, bots, or bulk operations) where long pre-push times are impractical:
106
+ - Document how to temporarily bypass the pre-push hook (standard Husky guidance) while keeping it enabled for interactive developer usage.
107
+ - Consider project-level policies for when bypassing is acceptable.
108
+ - If bypassing becomes common, reassess whether enforced full parity is still the right default.
109
+
110
+ Any significant change to pre-push behavior—including rolling back to `ci-verify:fast` as the main gate—**must** be accompanied by an ADR update or a new ADR that supersedes this one.
111
+
112
+ Created autonomously by voder.ai
@@ -0,0 +1,53 @@
1
+ ---
2
+ status: "accepted"
3
+ date: 2025-11-17
4
+ decision-makers: [Development Team]
5
+ consulted: [Implementation Plan, ESLint Documentation]
6
+ informed: [All Contributors]
7
+ ---
8
+
9
+ # Code Quality Ratcheting Plan
10
+
11
+ ## Context and Decision Drivers
12
+
13
+ The project currently enforces maintainability through ESLint rules `max-lines-per-function` and `complexity` with thresholds that allow overly large functions and moderately high cyclomatic complexity. While these thresholds have kept development velocity high, they permit functions and branches that are too complex to maintain effectively over time.
14
+
15
+ To systematically improve code quality and maintainability, we will implement an incremental ratcheting plan that gradually tightens these ESLint rules across multiple sprints, ensuring continuous improvement without large-scale refactors in a single release.
16
+
17
+ ## Considered Options
18
+
19
+ 1. **Immediate Strict Enforcement**: Set aggressive thresholds (e.g., 50 lines/function, complexity max 10) immediately.
20
+ 2. **No Change**: Maintain current thresholds indefinitely.
21
+ 3. **Incremental Ratcheting**: Gradually reduce thresholds over successive sprints.
22
+
23
+ ### Decision Outcome
24
+
25
+ We choose **Incremental Ratcheting** (Option 3) to balance maintainability improvements with manageable refactoring efforts.
26
+
27
+ ## Ratcheting Schedule
28
+
29
+ | Sprint | `max-lines-per-function` | `complexity` | Success Criteria |
30
+ | -------------- | -----------------------: | -------------------: | ------------------------------------------- |
31
+ | Now (Sprint 0) | 65 | 18 | No ESLint violations against new thresholds |
32
+ | Sprint 1 (2w) | 60 | 16 | All functions ≤60 lines, all methods comply |
33
+ | Sprint 2 (4w) | 55 | 14 | All functions ≤55 lines, complexity ≤14 |
34
+ | Sprint 3 (6w) | 50 | 12 | All functions ≤50 lines, complexity ≤12 |
35
+ | Final Review | Default (revert) | Default (see ESLint) | Remove explicit overrides, rely on defaults |
36
+
37
+ - **Timeline**: Each sprint is bi-weekly (2 weeks) aligned with release cycles.
38
+ - **Metrics**: ESLint violations count per rule must be zero at each milestone.
39
+ - **Automation**: CI will enforce thresholds and fail builds on any violations.
40
+
41
+ ## Implementation Steps
42
+
43
+ 1. Update `eslint.config.js` to set the `max-lines-per-function` and `complexity` rules to the Sprint 0 values.
44
+ 2. Configure CI/CD to fail on any rule violations by running `npm run lint -- --max-warnings=0`.
45
+ 3. Identify and refactor existing functions and branches that exceed the new thresholds.
46
+ 4. At the end of each sprint, verify zero violations, then ratchet thresholds to the next values.
47
+ 5. After the final Sprint, remove explicit rule overrides to revert to ESLint defaults.
48
+
49
+ ## Future Review
50
+
51
+ - At each sprint boundary, review the ratcheting plan and adjust if necessary.
52
+ - Consider additional ratcheting for other style rules (e.g., `max-lines-per-file`, `max-params`).
53
+ - Document the ratcheting process in CONTRIBUTING.md for new contributors.
@@ -0,0 +1,238 @@
1
+ # Dependency Health and dry-aged-deps Usage
2
+
3
+ This document explains how we assess and maintain dependency health in this project, with a focus on the `dry-aged-deps` maturity tool, how it interacts with our CI/CD pipeline, and how its outputs are incorporated into security incident and risk-acceptance records.
4
+
5
+ This is **internal/development-facing documentation** for maintainers and advanced contributors. The guarantees in the README and other user docs are **plain-language summaries** that are _backed by_ the processes described here, not the other way around.
6
+
7
+ ## Canonical Commands
8
+
9
+ Contributors and automation **must** use the following npm scripts when working with dependency health.
10
+
11
+ ### 1. Dependency maturity (dry-aged-deps)
12
+
13
+ We use [`dry-aged-deps`](https://github.com/voder-ai/dry-aged-deps) to identify dependency upgrade candidates that are both time-tested and free from known vulnerabilities, for **both production and development dependencies**.
14
+
15
+ - **Script**: `npm run deps:maturity`
16
+ - **CLI**: `dry-aged-deps`
17
+
18
+ Run with JSON output (recommended for reviews and CI tooling):
19
+
20
+ ```bash
21
+ npm run deps:maturity -- --format=json
22
+ ```
23
+
24
+ To additionally enforce exit codes based on health status, use the `--check` flag:
25
+
26
+ ```bash
27
+ npm run deps:maturity -- --format=json --check
28
+ ```
29
+
30
+ The JSON report is written to **stdout**. In CI, `npm run safety:deps` wraps this command and persists the latest report to `ci/dry-aged-deps.json` as a build artifact for later inspection and for use in incident documentation.
31
+
32
+ **Important behavior:**
33
+
34
+ - `dry-aged-deps` is **advisory only**:
35
+ - It **does not** automatically modify `package.json`, `package-lock.json`, or install anything.
36
+ - It **does not** auto-upgrade dependencies in CI or locally.
37
+ - All dependency changes are made explicitly (e.g., via `npm install`, `npm update`, or manual edits), and then reviewed through normal PR and release processes.
38
+ - `--check` can cause CI to fail if health thresholds are not met, but it still does **not** apply any changes; it only reports and signals status.
39
+
40
+ ### 2. Production security audit
41
+
42
+ For production (runtime) dependencies, we use npm’s built-in audit with modern flags:
43
+
44
+ ```bash
45
+ npm audit --omit=dev --audit-level=high
46
+ ```
47
+
48
+ This command is part of `npm run ci-verify:full` and is executed automatically in CI and the Husky pre-push hook. It must pass (no high-severity issues in the **production** dependency tree) for a release to proceed.
49
+
50
+ The JSON output from broader audits (see below) is used as evidence in:
51
+
52
+ - Security incident reports.
53
+ - Known-error records.
54
+ - Architecture/decision records related to dependency risk.
55
+
56
+ ### 3. Dev-dependency audit and safety checks
57
+
58
+ Dev-only vulnerabilities are tracked separately and **do not** block CI by themselves, but they must be documented and reviewed:
59
+
60
+ - `npm run audit:dev-high` – runs a dev-only audit using `npm audit --include=dev --audit-level=high --json`, normalizes the result to always exit with code `0` (never failing CI directly), and writes the JSON output to `ci/npm-audit.json` for targeted inspection of high-severity dev-only vulnerabilities.
61
+ - `npm run audit:ci` – runs `npm audit --json` and writes `ci/npm-audit.json` for CI artifacts.
62
+ - `npm run safety:deps` – runs `dry-aged-deps` with JSON output and writes `ci/dry-aged-deps.json`.
63
+
64
+ The dev audit focuses **exclusively** on dev dependencies via `npm audit --include=dev --audit-level=high --json`. It is designed **never to fail CI** (the script forces an exit code of `0`), and its JSON output is stored at `ci/npm-audit.json` for inspection alongside the full audit.
65
+
66
+ These scripts are wired into `ci-verify:full` and the GitHub Actions pipeline and, together with `dry-aged-deps` reports, form the evidence base for:
67
+
68
+ - Security incident investigations.
69
+ - Known-error documentation when dev-only vulnerabilities are accepted.
70
+ - Validating the claims we make in user-facing docs (e.g., the README).
71
+
72
+ ## How dry-aged-deps Guides Upgrades
73
+
74
+ `dry-aged-deps` evaluates available versions against configurable **age** and **security** thresholds for both production and development dependencies.
75
+
76
+ ### Current Configuration
77
+
78
+ In this project, the thresholds are currently equivalent for both groups:
79
+
80
+ ```json
81
+ {
82
+ "prod": { "minAge": 7, "minSeverity": "none" },
83
+ "dev": { "minAge": 7, "minSeverity": "none" }
84
+ }
85
+ ```
86
+
87
+ Explicitly:
88
+
89
+ 1. **7-day minimum age**
90
+ - A candidate version must have been published for **at least 7 days** (`minAge: 7`).
91
+ - This applies to **both**:
92
+ - Production dependencies (`prod`)
93
+ - Development dependencies (`dev`)
94
+
95
+ 2. **"none" minimum severity**
96
+ - `minSeverity: "none"` means **any known vulnerability** (even low-severity) disqualifies a version as a "safe" update.
97
+ - For a version to be considered a safe candidate upgrade by `dry-aged-deps`, it must:
98
+ - Be at least 7 days old.
99
+ - Have **zero** known vulnerabilities of any severity.
100
+
101
+ When `dry-aged-deps` finds no qualifying candidates under these constraints:
102
+
103
+ - `summary.totalOutdated` and `summary.safeUpdates` will both be `0`.
104
+ - `packages` will be an empty array.
105
+
106
+ This state is a **signal** that:
107
+
108
+ - Either we are already on the latest qualifying versions under the configured thresholds, or
109
+ - All newer versions are either too recent (younger than 7 days) or have at least one known vulnerability.
110
+
111
+ ### Advisory Role in Upgrade Decisions
112
+
113
+ Because `dry-aged-deps` is advisory and non-mutating:
114
+
115
+ - It **highlights** which dependency updates are both:
116
+ - Maturity-qualified (age ≥ 7 days).
117
+ - Vulnerability-free (`minSeverity: "none"`).
118
+ - It **does not**:
119
+ - Change dependency files.
120
+ - Automatically apply any upgrades in CI.
121
+
122
+ Maintainership responsibilities:
123
+
124
+ - Use the JSON report (especially `ci/dry-aged-deps.json` from CI) during dependency review to:
125
+ - Identify safe upgrade paths for both prod and dev dependencies.
126
+ - Understand when no safe upgrade path currently exists under the configured criteria.
127
+ - Make explicit, manual changes to dependencies, then re-run:
128
+ - `npm run deps:maturity -- --format=json --check`
129
+ - `npm audit --omit=dev --audit-level=high`
130
+ - Relevant audit scripts
131
+ to validate the updated state before merging and releasing.
132
+
133
+ ## How dry-aged-deps, npm audit, and Incident Records Interact
134
+
135
+ `dry-aged-deps` reports and npm audit outputs are used together to:
136
+
137
+ 1. Determine **release readiness** for production dependencies.
138
+ 2. Document and justify any **accepted risks**, especially for dev-only tooling.
139
+ 3. Provide **evidence backing** for the security-related statements in the README and other user-facing docs.
140
+
141
+ ### Evidence for Production-Side Guarantees
142
+
143
+ Our user-facing docs (e.g., the README) state that published versions of this project do not contain any _known_ high-severity vulnerabilities in their **production dependency tree** at release time.
144
+
145
+ Internally, this claim is backed by:
146
+
147
+ - Successful execution of:
148
+ - `npm audit --omit=dev --audit-level=high`
149
+ - Verification that:
150
+ - The audit reports **0 high-severity** production vulnerabilities.
151
+ - Corroborating context from:
152
+ - `dry-aged-deps` reports (for availability of mature, vulnerability-free upgrades).
153
+
154
+ If these conditions are not met, a release is not allowed to proceed under normal circumstances, and a security incident or exception process is invoked.
155
+
156
+ ### Handling Dev-Only Vulnerabilities and Semantic-Release/npm
157
+
158
+ Some high-severity vulnerabilities exist in **dev-only tooling**, specifically in the semantic-release/npm toolchain, which is used only in CI/release workflows, not at runtime in production environments.
159
+
160
+ Current handling:
161
+
162
+ - `npm audit --include=dev --audit-level=high --json` (via `npm run audit:dev-high` and `npm run audit:ci`) identifies these vulnerabilities and writes **dev-focused** and **full** audit results to `ci/npm-audit.json`.
163
+ - `dry-aged-deps` is run with the same strict thresholds for dev dependencies:
164
+ - `minAge: 7`
165
+ - `minSeverity: "none"`
166
+
167
+ Under these thresholds, `dry-aged-deps` currently reports:
168
+
169
+ - No safe upgrade path (no candidate versions that are both ≥ 7 days old and vulnerability-free) for certain semantic-release/npm–related packages.
170
+
171
+ As a result:
172
+
173
+ - We **intentionally continue** to use the existing semantic-release/npm toolchain.
174
+ - We record and manage this as an **accepted dev-only risk**, not a production risk.
175
+
176
+ This acceptance is formalized and supported by:
177
+
178
+ - A **known error** record:
179
+ - `docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md`
180
+ - An **architecture/decision record** (ADR):
181
+ - `docs/decisions/adr-accept-dev-dep-risk-glob.md`
182
+ - CI artifacts:
183
+ - `ci/npm-audit.json`
184
+ - `ci/dry-aged-deps.json`
185
+
186
+ These documents and artifacts show:
187
+
188
+ - What the vulnerabilities are.
189
+ - Where they live (dev-only, CI-only tooling).
190
+ - Why they are accepted (no safe, mature, vulnerability-free alternatives under our thresholds).
191
+ - What compensating controls are in place.
192
+
193
+ ### Compensating Controls for Accepted Dev-Only Risk
194
+
195
+ Because `dry-aged-deps` currently identifies **no safe upgrade path** (under the 7-day / `"none"` thresholds) that would resolve these bundled dev-only vulnerabilities, we:
196
+
197
+ - Keep the existing semantic-release/npm toolchain in place.
198
+ - Enforce the following compensating controls:
199
+ - CI isolation and hardened environments for release automation.
200
+ - Strict audits for **production** dependencies (must pass `npm audit --omit=dev --audit-level=high`).
201
+ - Explicit documentation via:
202
+ - Known-error and incident records.
203
+ - ADRs describing the rationale and review process.
204
+ - Periodically re-run and re-review:
205
+ - `npm run deps:maturity -- --format=json --check`
206
+ - `npm run audit:dev-high`
207
+ - `npm run audit:ci`
208
+ to see whether a new, safe, mature upgrade path has appeared.
209
+
210
+ These processes ensure that:
211
+
212
+ - End users see a concise, plain-language statement of security posture in the README and related docs.
213
+ - That statement is grounded in:
214
+ - Concrete `dry-aged-deps` configuration (7-day / `"none"` thresholds for prod and dev).
215
+ - Regular, automated `npm audit` runs.
216
+ - Documented incident handling and risk acceptance when no compliant upgrade path exists.
217
+
218
+ ## Current Status (2025-12-03, verified)
219
+
220
+ As of the latest review:
221
+
222
+ - `npm run deps:maturity -- --format=json --check` reports:
223
+ - `totalOutdated: 0`
224
+ - `safeUpdates: 0`
225
+ - `packages: []`
226
+ - `npm audit --omit=dev --audit-level=high` reports **0 high-severity** vulnerabilities for production dependencies.
227
+ - Remaining high-severity issues are limited to **dev-only tooling** (the semantic-release/npm toolchain) and are documented as a **known error**:
228
+ - `docs/security-incidents/SECURITY-INCIDENT-2025-11-18-semantic-release-bundled-npm.known-error.md`
229
+ - `docs/decisions/adr-accept-dev-dep-risk-glob.md`
230
+
231
+ This combination of:
232
+
233
+ - Advisory `dry-aged-deps` checks (with 7-day / `"none"` thresholds for prod and dev),
234
+ - Mandatory production-only `npm audit` gating,
235
+ - Non-blocking but fully recorded dev-only audits, and
236
+ - Documented risk acceptance for the semantic-release/npm toolchain
237
+
238
+ is what underpins the security-related guarantees we present to users in the README and other user-facing documentation.