@xenos1996/usat 1.0.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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +335 -0
  3. package/USAT.md +596 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +438 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/config.d.ts +7 -0
  9. package/dist/config.d.ts.map +1 -0
  10. package/dist/config.js +72 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/detect/index.d.ts +58 -0
  13. package/dist/detect/index.d.ts.map +1 -0
  14. package/dist/detect/index.js +329 -0
  15. package/dist/detect/index.js.map +1 -0
  16. package/dist/engine/audit.d.ts +21 -0
  17. package/dist/engine/audit.d.ts.map +1 -0
  18. package/dist/engine/audit.js +295 -0
  19. package/dist/engine/audit.js.map +1 -0
  20. package/dist/engine/diff.d.ts +24 -0
  21. package/dist/engine/diff.d.ts.map +1 -0
  22. package/dist/engine/diff.js +136 -0
  23. package/dist/engine/diff.js.map +1 -0
  24. package/dist/engine/evaluate.d.ts +19 -0
  25. package/dist/engine/evaluate.d.ts.map +1 -0
  26. package/dist/engine/evaluate.js +377 -0
  27. package/dist/engine/evaluate.js.map +1 -0
  28. package/dist/engine/gate.d.ts +19 -0
  29. package/dist/engine/gate.d.ts.map +1 -0
  30. package/dist/engine/gate.js +47 -0
  31. package/dist/engine/gate.js.map +1 -0
  32. package/dist/engine/loader.d.ts +22 -0
  33. package/dist/engine/loader.d.ts.map +1 -0
  34. package/dist/engine/loader.js +360 -0
  35. package/dist/engine/loader.js.map +1 -0
  36. package/dist/engine/maturity.d.ts +20 -0
  37. package/dist/engine/maturity.d.ts.map +1 -0
  38. package/dist/engine/maturity.js +157 -0
  39. package/dist/engine/maturity.js.map +1 -0
  40. package/dist/engine/score.d.ts +19 -0
  41. package/dist/engine/score.d.ts.map +1 -0
  42. package/dist/engine/score.js +141 -0
  43. package/dist/engine/score.js.map +1 -0
  44. package/dist/engine/sections.d.ts +14 -0
  45. package/dist/engine/sections.d.ts.map +1 -0
  46. package/dist/engine/sections.js +50 -0
  47. package/dist/engine/sections.js.map +1 -0
  48. package/dist/index.d.ts +23 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +17 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/report/markdown.d.ts +16 -0
  53. package/dist/report/markdown.d.ts.map +1 -0
  54. package/dist/report/markdown.js +488 -0
  55. package/dist/report/markdown.js.map +1 -0
  56. package/dist/types.d.ts +282 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +16 -0
  59. package/dist/types.js.map +1 -0
  60. package/dist/util/glob.d.ts +11 -0
  61. package/dist/util/glob.d.ts.map +1 -0
  62. package/dist/util/glob.js +86 -0
  63. package/dist/util/glob.js.map +1 -0
  64. package/dist/util/project.d.ts +72 -0
  65. package/dist/util/project.d.ts.map +1 -0
  66. package/dist/util/project.js +586 -0
  67. package/dist/util/project.js.map +1 -0
  68. package/dist/util/yaml.d.ts +28 -0
  69. package/dist/util/yaml.d.ts.map +1 -0
  70. package/dist/util/yaml.js +48 -0
  71. package/dist/util/yaml.js.map +1 -0
  72. package/docs/ARCHITECTURE.md +119 -0
  73. package/docs/README.md +27 -0
  74. package/docs/adr/0001-record-architecture-decisions.md +35 -0
  75. package/docs/adr/0002-typescript-engine-over-python.md +49 -0
  76. package/docs/adr/0003-rules-are-data-not-code.md +50 -0
  77. package/docs/adr/0004-markdown-only-output.md +41 -0
  78. package/docs/adr/0005-maturity-dampens-severity.md +56 -0
  79. package/docs/adr/0006-severity-status-two-axes.md +48 -0
  80. package/docs/adr/0007-suppressions-are-visible-and-expiring.md +46 -0
  81. package/docs/adr/0008-report-trailer-and-diff.md +48 -0
  82. package/docs/adr/0009-fail-closed-on-malformed-input.md +56 -0
  83. package/docs/adr/0010-detector-design.md +54 -0
  84. package/docs/adr/0011-coexist-with-deep-scanners.md +52 -0
  85. package/docs/adr/README.md +32 -0
  86. package/docs/agent-integration.md +129 -0
  87. package/docs/ci-integration.md +163 -0
  88. package/docs/concepts.md +196 -0
  89. package/docs/configuration.md +105 -0
  90. package/docs/detectors.md +186 -0
  91. package/docs/getting-started.md +99 -0
  92. package/docs/maturity-profiles.md +156 -0
  93. package/docs/reference/api.md +193 -0
  94. package/docs/reference/cli.md +412 -0
  95. package/docs/rule-packs.md +278 -0
  96. package/docs/standards-mapping.md +171 -0
  97. package/package.json +96 -0
  98. package/rules/core/architecture.yaml +190 -0
  99. package/rules/core/cicd.yaml +212 -0
  100. package/rules/core/code-quality.yaml +261 -0
  101. package/rules/core/dependencies.yaml +132 -0
  102. package/rules/core/documentation.yaml +119 -0
  103. package/rules/core/future-readiness.yaml +91 -0
  104. package/rules/core/release.yaml +131 -0
  105. package/rules/core/repo.yaml +303 -0
  106. package/rules/core/security.yaml +494 -0
  107. package/rules/core/supply-chain.yaml +357 -0
  108. package/rules/core/testing.yaml +260 -0
  109. package/rules/detectors.yaml +2255 -0
  110. package/rules/index.yaml +41 -0
  111. package/rules/profiles/maturity.yaml +135 -0
  112. package/rules/stacks/ai-era.yaml +193 -0
  113. package/rules/stacks/api-backend.yaml +121 -0
  114. package/rules/stacks/cli.yaml +105 -0
  115. package/rules/stacks/compliance.yaml +157 -0
  116. package/rules/stacks/containers.yaml +124 -0
  117. package/rules/stacks/data.yaml +165 -0
  118. package/rules/stacks/go.yaml +134 -0
  119. package/rules/stacks/iac.yaml +128 -0
  120. package/rules/stacks/jvm.yaml +150 -0
  121. package/rules/stacks/ml-ai.yaml +140 -0
  122. package/rules/stacks/mobile.yaml +121 -0
  123. package/rules/stacks/node-typescript.yaml +166 -0
  124. package/rules/stacks/python.yaml +175 -0
  125. package/rules/stacks/rust.yaml +129 -0
  126. package/rules/stacks/solidity.yaml +139 -0
  127. package/rules/stacks/web-frontend.yaml +159 -0
  128. package/templates/AGENTS.audit.md +135 -0
  129. package/templates/AUDIT_REPORT.md +155 -0
@@ -0,0 +1,132 @@
1
+ id: core/dependencies
2
+ title: Dependencies & Third-Party
3
+ section: S10
4
+ section_title: Dependencies & Third-Party
5
+ description: >
6
+ Every dependency is a bet on someone else's maintenance discipline.
7
+ USAT scores the observable parts and hands the rest to review.
8
+ version: '1.0'
9
+
10
+ rules:
11
+ - id: DEP-001
12
+ title: Dependencies are declared in a manifest
13
+ section: S10
14
+ section_title: Dependencies & Third-Party
15
+ severity: MEDIUM
16
+ class: supply-chain
17
+ check:
18
+ kind: any_file
19
+ patterns:
20
+ [
21
+ 'package.json',
22
+ 'pyproject.toml',
23
+ 'requirements*.txt',
24
+ 'Cargo.toml',
25
+ 'go.mod',
26
+ 'pom.xml',
27
+ 'build.gradle*',
28
+ 'composer.json',
29
+ 'Gemfile',
30
+ 'Package.swift',
31
+ 'pubspec.yaml',
32
+ 'mix.exs',
33
+ ]
34
+ why: 'Undeclared dependencies mean the build works on one machine and nowhere else.'
35
+ remediation: 'Declare every import in the manifest; pin transitive risk with a lockfile.'
36
+ references: ['NIST-SSDF-PS.3.2']
37
+
38
+ - id: DEP-002
39
+ title: No known-HIGH/CRITICAL vulnerabilities in dependencies
40
+ section: S10
41
+ section_title: Dependencies & Third-Party
42
+ severity: HIGH
43
+ class: supply-chain
44
+ check:
45
+ kind: command
46
+ run: '! (npm audit --production --audit-level=high 2>/dev/null | grep -qiE "critical|high")'
47
+ expect_exit: 0
48
+ evidence: '`npm audit` / `pip-audit` / `osv-scanner` / `trivy fs` output dated today.'
49
+ why: 'Most modern compromises arrive through a transitive dependency, not your own code.'
50
+ remediation: 'Patch or replace the flagged package; if no fix exists, pin an unaffected version or drop the dependency.'
51
+ references: ['OpenSSF-Scorecard:Vulnerabilities', 'NIST-SSDF-RV.1.1']
52
+
53
+ - id: DEP-003
54
+ title: Dependencies are actively maintained
55
+ section: S10
56
+ section_title: Dependencies & Third-Party
57
+ severity: MEDIUM
58
+ class: supply-chain
59
+ depths: [deep]
60
+ check: { kind: manual }
61
+ evidence: 'For the top 10 direct dependencies: last release date, open-issue trend, and bus factor.'
62
+ why: 'An unmaintained dependency is a future incident you have already scheduled.'
63
+ remediation: 'Replace anything with no release in 24+ months, or fork it deliberately and own the fork.'
64
+ references: ['OpenSSF-Scorecard:Maintained', 'OpenSSF-Criticality-Score']
65
+
66
+ - id: DEP-004
67
+ title: No obviously redundant dependencies
68
+ section: S10
69
+ section_title: Dependencies & Third-Party
70
+ severity: LOW
71
+ class: maintainability
72
+ check: { kind: manual }
73
+ evidence: 'Two libraries doing the same job (e.g. both axios and node-fetch; both moment and date-fns).'
74
+ why: 'Two HTTP clients means two sets of CVEs, two upgrade paths, and an argument every PR.'
75
+ remediation: 'Pick one per concern and migrate; add a lint rule banning the loser.'
76
+ references: ['OpenSSF-Scorecard']
77
+
78
+ - id: DEP-005
79
+ title: Unused dependencies are pruned
80
+ section: S10
81
+ section_title: Dependencies & Third-Party
82
+ severity: LOW
83
+ class: maintainability
84
+ applies_when: { fact: 'pm:npm' }
85
+ check:
86
+ kind: command
87
+ run: '! (npx --yes depcheck@latest --json 2>/dev/null | grep -qE "\"unused\": \\[[^]]+\\]")'
88
+ expect_exit: 0
89
+ why: >-
90
+ Unused dependencies still install, still scan, and still produce CVEs. They are pure liability with no benefit.
91
+ evidence: 'depcheck / knip / pip-extra-reqs output.'
92
+ remediation: 'Remove unused packages; they still count against your CVE surface and install time.'
93
+ references: ['NIST-SSDF-PS.3.2']
94
+
95
+ - id: DEP-006
96
+ title: Licenses are compatible with the project license
97
+ section: S10
98
+ section_title: Dependencies & Third-Party
99
+ severity: MEDIUM
100
+ class: compliance
101
+ check: { kind: manual }
102
+ evidence: 'An SPDX license inventory of direct dependencies and any GPL/AGPL entries in a permissively-licensed or commercial project.'
103
+ why: 'One AGPL transitive dependency can force disclosure of your entire source.'
104
+ remediation: 'Generate an SBOM, run a license policy check in CI, and review anything copyleft before shipping.'
105
+ references: ['SPDX', 'OpenSSF-Scorecard:License', 'EU-CRA']
106
+
107
+ - id: DEP-007
108
+ title: External services have documented failure modes
109
+ section: S10
110
+ section_title: Dependencies & Third-Party
111
+ severity: MEDIUM
112
+ class: operations
113
+ applies_when:
114
+ not: { fact: 'maturity:prototype' }
115
+ check: { kind: manual }
116
+ evidence: 'For each third-party API you call: timeout, retry policy, and what the user sees when it is down.'
117
+ why: 'Your uptime is the product of every service you depend on, unless you degrade gracefully.'
118
+ remediation: 'Set explicit timeouts, bounded retries with jitter, circuit breakers, and a fallback path per integration.'
119
+ references: ['NIST-SSDF-PW.4', 'Release-It']
120
+
121
+ - id: DEP-008
122
+ title: Webhook payloads are signature-verified
123
+ section: S10
124
+ section_title: Dependencies & Third-Party
125
+ severity: HIGH
126
+ class: security
127
+ applies_when: { fact: 'has:payments' }
128
+ check: { kind: manual }
129
+ evidence: 'The webhook handler: file:line where the provider signature (HMAC) is verified before the payload is trusted.'
130
+ why: 'An unverified webhook endpoint is an unauthenticated API that writes to your database.'
131
+ remediation: 'Verify the provider HMAC over the raw body with a constant-time comparison before processing.'
132
+ references: ['CWE-345', 'ASVS-13.2.2']
@@ -0,0 +1,119 @@
1
+ id: core/documentation
2
+ title: Documentation & Knowledge
3
+ section: S12
4
+ section_title: Documentation & Knowledge
5
+ description: >
6
+ Documentation is the only part of the system that ships to every future
7
+ maintainer. USAT checks the artefacts exist and then asks whether they are true.
8
+ version: '1.0'
9
+
10
+ rules:
11
+ - id: DOC-001
12
+ title: README covers what / install / run / contribute
13
+ section: S12
14
+ section_title: Documentation & Knowledge
15
+ severity: MEDIUM
16
+ class: documentation
17
+ applies_when: { fact: 'doc:readme' }
18
+ check: { kind: manual }
19
+ evidence: 'The four headings. If any is missing, the README fails this check.'
20
+ why: 'A README that only says the project name is a README-shaped placeholder.'
21
+ remediation: 'Four sections: what it is, how to install, how to run it locally, how to contribute.'
22
+ references: ['CII-Best-Practices']
23
+
24
+ - id: DOC-002
25
+ title: Setup instructions have been verified recently
26
+ section: S12
27
+ section_title: Documentation & Knowledge
28
+ severity: MEDIUM
29
+ class: documentation
30
+ check: { kind: manual }
31
+ evidence: 'A clean-machine clone-and-run within the last quarter, or CI that installs from scratch on every PR.'
32
+ why: 'Setup docs rot faster than any other file, and the cost lands on whoever joins next.'
33
+ remediation: 'Run the README steps in a container from scratch; fix every command that fails.'
34
+ references: ['CII-Best-Practices']
35
+
36
+ - id: DOC-003
37
+ title: Public APIs are documented
38
+ section: S12
39
+ section_title: Documentation & Knowledge
40
+ severity: MEDIUM
41
+ class: documentation
42
+ applies_when:
43
+ any:
44
+ - { fact: 'project:library' }
45
+ - { fact: 'project:api' }
46
+ - { fact: 'doc:api-reference' }
47
+ check:
48
+ kind: any_file
49
+ patterns:
50
+ [
51
+ '**/openapi.{yaml,yml,json}',
52
+ '**/swagger.{yaml,yml,json}',
53
+ '**/*.graphql',
54
+ 'docs/api/**',
55
+ 'docs/reference/**',
56
+ '**/*.d.ts',
57
+ ]
58
+ why: 'For a library or API, the docs are the product surface.'
59
+ remediation: 'Publish an OpenAPI spec or typedoc/jsdoc output; generate it in CI so it cannot drift silently.'
60
+ references: ['OpenAPI', 'OpenSSF-Scorecard']
61
+
62
+ - id: DOC-004
63
+ title: Complex logic is explained at the point of use
64
+ section: S12
65
+ section_title: Documentation & Knowledge
66
+ severity: LOW
67
+ class: documentation
68
+ check: { kind: manual }
69
+ evidence: 'Two non-obvious modules: does a comment explain WHY, not WHAT?'
70
+ why: 'Code tells you what it does. Only a comment can tell you why the obvious solution was wrong.'
71
+ remediation: 'Comment the surprising parts: workarounds, invariants, and anything you had to look up twice.'
72
+ references: ['Clean-Code']
73
+
74
+ - id: DOC-005
75
+ title: Docs live in the repo with the code
76
+ section: S12
77
+ section_title: Documentation & Knowledge
78
+ severity: LOW
79
+ class: documentation
80
+ check:
81
+ kind: any_file
82
+ patterns: ['docs/**', '**/*.md']
83
+ why: 'Docs in a separate wiki are docs that outlive nobody and get updated by no one.'
84
+ remediation: 'Move docs next to the code so they are reviewed in the same PR.'
85
+ references: ['Docs-as-Code']
86
+
87
+ - id: DOC-006
88
+ title: An onboarding path exists
89
+ section: S12
90
+ section_title: Documentation & Knowledge
91
+ severity: LOW
92
+ class: documentation
93
+ applies_when: { fact: 'metric:contributors', op: 'gt', value: 2 }
94
+ check:
95
+ kind: any_file
96
+ patterns:
97
+ [
98
+ '**/ONBOARDING*',
99
+ '**/onboarding*',
100
+ 'docs/GETTING_STARTED*',
101
+ 'docs/getting-started*',
102
+ 'docs/onboarding/**',
103
+ ]
104
+ why: 'Without it, onboarding is a series of interruptions for whoever has been there longest.'
105
+ remediation: 'A single page: architecture in five bullets, setup, the three commands you need, and who to ask.'
106
+ references: ['CII-Best-Practices']
107
+
108
+ - id: DOC-007
109
+ title: Documentation examples are tested
110
+ section: S12
111
+ section_title: Documentation & Knowledge
112
+ severity: FUTURE
113
+ class: documentation
114
+ applies_when: { fact: 'project:library' }
115
+ check: { kind: manual }
116
+ evidence: 'Doctests, README code blocks executed in CI, or example apps built against the published API.'
117
+ why: 'The only thing worse than no example is an example that no longer works.'
118
+ remediation: 'Run README snippets in CI (mdsh, pytest-examples, or a small example app).'
119
+ references: ['Docs-as-Code']
@@ -0,0 +1,91 @@
1
+ id: core/future-readiness
2
+ title: Future Readiness
3
+ section: S16
4
+ section_title: Future Readiness
5
+ description: >
6
+ Not needed today, expensive to bolt on later. These are plans, not defects —
7
+ every rule here is FUTURE severity and never blocks a release.
8
+ version: '1.0'
9
+
10
+ rules:
11
+ - id: FUT-001
12
+ title: A path off the current architecture exists
13
+ section: S16
14
+ section_title: Future Readiness
15
+ severity: FUTURE
16
+ class: maintainability
17
+ applies_when: { fact: 'maturity:production' }
18
+ check: { kind: manual }
19
+ evidence: 'A written note on what the current architecture stops supporting (scale, team size, latency) and what you would do about it.'
20
+ why: 'Every architecture has a ceiling. Knowing where yours is turns a crisis into a project.'
21
+ remediation: 'Write one page: current limits, the trigger that would force a change, and the likely direction.'
22
+ references: ['Team-Topologies']
23
+
24
+ - id: FUT-002
25
+ title: No core technology is at or near end of life
26
+ section: S16
27
+ section_title: Future Readiness
28
+ severity: FUTURE
29
+ class: maintainability
30
+ check: { kind: manual }
31
+ evidence: 'Runtime version, framework major versions, and their upstream EOL dates.'
32
+ why: 'Node 16, Python 3.8, and CentOS 7 all had an EOL date that everyone knew about in advance.'
33
+ remediation: 'Track EOL dates in the README; schedule upgrades one major behind current, never two.'
34
+ references: ['endoflife.date']
35
+
36
+ - id: FUT-003
37
+ title: Data archiving strategy exists
38
+ section: S16
39
+ section_title: Future Readiness
40
+ severity: FUTURE
41
+ class: operations
42
+ applies_when: { fact: 'has:database' }
43
+ check: { kind: manual }
44
+ evidence: 'Retention policy per table/dataset and where cold data goes.'
45
+ why: 'A table nobody can archive eventually makes every query slow and every migration terrifying.'
46
+ remediation: 'Define retention per dataset; partition by time; move cold rows to object storage.'
47
+ references: ['AWS-Well-Architected']
48
+
49
+ - id: FUT-004
50
+ title: Multi-region or failover is at least designed
51
+ section: S16
52
+ section_title: Future Readiness
53
+ severity: FUTURE
54
+ class: operations
55
+ applies_when: { fact: 'maturity:production' }
56
+ check: { kind: manual }
57
+ evidence: 'Either a multi-region design, or a documented decision to accept single-region risk (with an RTO you have told customers about).'
58
+ why: 'You do not have to run multi-region. You do have to have decided.'
59
+ remediation: 'Document the decision; if single-region, keep backups cross-region so recovery is possible.'
60
+ references: ['AWS-Well-Architected:Reliability']
61
+
62
+ - id: FUT-005
63
+ title: A tech radar or equivalent exists
64
+ section: S16
65
+ section_title: Future Readiness
66
+ severity: FUTURE
67
+ class: maintainability
68
+ applies_when: { fact: 'metric:contributors', op: 'gt', value: 4 }
69
+ check: { kind: manual }
70
+ evidence: 'A document listing technologies as adopt / trial / assess / hold, last reviewed within 12 months.'
71
+ why: 'Without it, every new project re-litigates the same choices with whoever argues hardest.'
72
+ remediation: 'Create a one-page radar; review it quarterly.'
73
+ references: ['Thoughtworks-Tech-Radar']
74
+
75
+ - id: FUT-006
76
+ title: Cost/usage is monitored
77
+ section: S16
78
+ section_title: Future Readiness
79
+ severity: FUTURE
80
+ class: operations
81
+ applies_when:
82
+ any:
83
+ - { fact: 'has:serverless' }
84
+ - { fact: 'has:kubernetes' }
85
+ - { fact: 'has:terraform' }
86
+ - { fact: 'ai:llm-sdk' }
87
+ check: { kind: manual }
88
+ evidence: 'Cloud billing alerts, per-service cost attribution, or LLM token spend tracking.'
89
+ why: 'The bill is the one metric that always surprises people, usually quarterly.'
90
+ remediation: 'Tag resources by service; set budget alerts at 50/80/100%; review the top five line items monthly.'
91
+ references: ['FinOps', 'AWS-Well-Architected:Cost']
@@ -0,0 +1,131 @@
1
+ id: core/release
2
+ title: Release & Change Management
3
+ section: S9
4
+ section_title: Release & Change Management
5
+ description: >
6
+ How a merged commit becomes a version someone else depends on. This section
7
+ is what separates "we deploy" from "we ship".
8
+ version: '1.0'
9
+
10
+ rules:
11
+ - id: REL-001
12
+ title: Versioning is semantic and consistent
13
+ section: S9
14
+ section_title: Release & Change Management
15
+ severity: MEDIUM
16
+ class: maintainability
17
+ applies_when:
18
+ not: { fact: 'maturity:prototype' }
19
+ check: { kind: manual }
20
+ evidence: 'Current version, and whether MAJOR/MINOR/PATCH changes match SemVer in practice.'
21
+ why: 'Consumers (including your future self) need to know whether upgrading is safe.'
22
+ remediation: 'Adopt SemVer; automate version bumps from Conventional Commits (Changesets, semantic-release).'
23
+ references: ['SemVer', 'OpenSSF-Scorecard:Signed-Releases']
24
+
25
+ - id: REL-002
26
+ title: Releases are tagged in version control
27
+ section: S9
28
+ section_title: Release & Change Management
29
+ severity: MEDIUM
30
+ class: operations
31
+ applies_when:
32
+ not: { fact: 'maturity:prototype' }
33
+ check: { kind: manual }
34
+ evidence: '`git tag --list` output, or the release automation config that creates tags.'
35
+ why: 'Without tags, "what is running in production?" has no answer you can look up.'
36
+ remediation: 'Tag every release (v1.2.3) and deploy from the tag, not from a branch tip.'
37
+ references: ['SLSA-Source', 'OpenSSF-Scorecard:Signed-Releases']
38
+
39
+ - id: REL-003
40
+ title: Release notes are published
41
+ section: S9
42
+ section_title: Release & Change Management
43
+ severity: LOW
44
+ class: documentation
45
+ applies_when:
46
+ not: { fact: 'maturity:prototype' }
47
+ check:
48
+ kind: grep_present
49
+ pattern: '(semantic-release|release-drafter|changesets|changeset version|generate-notes|release_notes|changelog)'
50
+ include:
51
+ [
52
+ '.github/workflows/*.yml',
53
+ '.github/workflows/*.yaml',
54
+ '.github/release.yml',
55
+ 'package.json',
56
+ '.changeset/config.json',
57
+ 'Makefile',
58
+ ]
59
+ flags: i
60
+ why: 'A tag with no notes makes every upgrade an archaeology project for your users.'
61
+ remediation: 'Generate notes from commit scope; hand-edit the breaking-changes section.'
62
+ references: ['Keep-a-Changelog']
63
+
64
+ - id: REL-004
65
+ title: Risky changes sit behind a feature flag
66
+ section: S9
67
+ section_title: Release & Change Management
68
+ severity: LOW
69
+ class: operations
70
+ applies_when:
71
+ any:
72
+ - { fact: 'maturity:production' }
73
+ - { fact: 'maturity:beta' }
74
+ check:
75
+ kind: grep_present
76
+ pattern: '(launchdarkly|unleash|flagsmith|growthbook|posthog|openfeature|isFeatureEnabled|featureFlag|useFlag|flipper)'
77
+ include: ['**/*.{ts,tsx,js,jsx,py,go,rs,java,kt,rb}']
78
+ exclude: ['**/*.test.*', '**/node_modules/**']
79
+ flags: i
80
+ why: 'Deploy and release are different verbs. Flags let you deploy on Tuesday and release on Thursday.'
81
+ remediation: 'Wrap new behaviour in a flag with a default-off rollout and a documented kill switch.'
82
+ references: ['DORA', 'Progressive-Delivery']
83
+
84
+ - id: REL-005
85
+ title: Database migrations run forward and are reversible
86
+ section: S9
87
+ section_title: Release & Change Management
88
+ severity: HIGH
89
+ class: correctness
90
+ applies_when: { fact: 'has:database' }
91
+ check: { kind: manual }
92
+ evidence: 'Migration tool in use, and for the last destructive migration: the expand/contract or down-migration plan.'
93
+ why: 'A migration you cannot reverse is a one-way door taken during a deploy, usually at the worst moment.'
94
+ remediation: 'Use expand/contract: add column → backfill → switch reads → drop later. Keep down-migrations tested for everything else.'
95
+ references: ['NIST-SSDF-PO.5']
96
+
97
+ - id: REL-006
98
+ title: Migrations are separated from application deploys
99
+ section: S9
100
+ section_title: Release & Change Management
101
+ severity: MEDIUM
102
+ class: correctness
103
+ applies_when: { fact: 'has:database' }
104
+ check: { kind: manual }
105
+ evidence: 'Deploy order: does the schema change ship before the code that requires it?'
106
+ why: 'Deploying code and schema simultaneously means the old code briefly runs against the new schema.'
107
+ remediation: 'Run migrations as a separate, first step; keep every change backward-compatible with the currently deployed version.'
108
+ references: ['Expand-Contract']
109
+
110
+ - id: REL-007
111
+ title: There is a documented incident/runbook path
112
+ section: S9
113
+ section_title: Release & Change Management
114
+ severity: MEDIUM
115
+ class: operations
116
+ applies_when: { fact: 'maturity:production' }
117
+ check:
118
+ kind: any_file
119
+ patterns:
120
+ [
121
+ '**/RUNBOOK*',
122
+ '**/runbook*',
123
+ 'docs/runbooks/**',
124
+ 'runbooks/**',
125
+ 'docs/on-call*',
126
+ 'docs/incident*',
127
+ 'INCIDENT.md',
128
+ ]
129
+ why: 'The middle of an incident is the worst possible time to discover nobody wrote down how to restart the queue.'
130
+ remediation: 'One runbook per service: how to check health, restart, roll back, escalate, and who owns it.'
131
+ references: ['NIST-SSDF-RV.2', 'Google-SRE']