@xenos1996/usa 2.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.
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/USA.md +597 -0
- package/dist/bootstrap/catalog.d.ts +46 -0
- package/dist/bootstrap/catalog.d.ts.map +1 -0
- package/dist/bootstrap/catalog.js +312 -0
- package/dist/bootstrap/catalog.js.map +1 -0
- package/dist/bootstrap/index.d.ts +36 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +177 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +706 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +88 -0
- package/dist/config.js.map +1 -0
- package/dist/detect/index.d.ts +58 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/detect/index.js +329 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/engine/audit.d.ts +32 -0
- package/dist/engine/audit.d.ts.map +1 -0
- package/dist/engine/audit.js +366 -0
- package/dist/engine/audit.js.map +1 -0
- package/dist/engine/diff.d.ts +24 -0
- package/dist/engine/diff.d.ts.map +1 -0
- package/dist/engine/diff.js +136 -0
- package/dist/engine/diff.js.map +1 -0
- package/dist/engine/evaluate.d.ts +19 -0
- package/dist/engine/evaluate.d.ts.map +1 -0
- package/dist/engine/evaluate.js +377 -0
- package/dist/engine/evaluate.js.map +1 -0
- package/dist/engine/gate.d.ts +19 -0
- package/dist/engine/gate.d.ts.map +1 -0
- package/dist/engine/gate.js +47 -0
- package/dist/engine/gate.js.map +1 -0
- package/dist/engine/loader.d.ts +37 -0
- package/dist/engine/loader.d.ts.map +1 -0
- package/dist/engine/loader.js +388 -0
- package/dist/engine/loader.js.map +1 -0
- package/dist/engine/maturity.d.ts +20 -0
- package/dist/engine/maturity.d.ts.map +1 -0
- package/dist/engine/maturity.js +157 -0
- package/dist/engine/maturity.js.map +1 -0
- package/dist/engine/score.d.ts +19 -0
- package/dist/engine/score.d.ts.map +1 -0
- package/dist/engine/score.js +141 -0
- package/dist/engine/score.js.map +1 -0
- package/dist/engine/sections.d.ts +14 -0
- package/dist/engine/sections.d.ts.map +1 -0
- package/dist/engine/sections.js +50 -0
- package/dist/engine/sections.js.map +1 -0
- package/dist/evolution/benchmark.d.ts +12 -0
- package/dist/evolution/benchmark.d.ts.map +1 -0
- package/dist/evolution/benchmark.js +107 -0
- package/dist/evolution/benchmark.js.map +1 -0
- package/dist/evolution/capability.d.ts +22 -0
- package/dist/evolution/capability.d.ts.map +1 -0
- package/dist/evolution/capability.js +69 -0
- package/dist/evolution/capability.js.map +1 -0
- package/dist/evolution/coverage.d.ts +15 -0
- package/dist/evolution/coverage.d.ts.map +1 -0
- package/dist/evolution/coverage.js +65 -0
- package/dist/evolution/coverage.js.map +1 -0
- package/dist/evolution/gap.d.ts +10 -0
- package/dist/evolution/gap.d.ts.map +1 -0
- package/dist/evolution/gap.js +52 -0
- package/dist/evolution/gap.js.map +1 -0
- package/dist/evolution/propose.d.ts +50 -0
- package/dist/evolution/propose.d.ts.map +1 -0
- package/dist/evolution/propose.js +188 -0
- package/dist/evolution/propose.js.map +1 -0
- package/dist/evolution/queue.d.ts +64 -0
- package/dist/evolution/queue.d.ts.map +1 -0
- package/dist/evolution/queue.js +192 -0
- package/dist/evolution/queue.js.map +1 -0
- package/dist/evolution/release.d.ts +11 -0
- package/dist/evolution/release.d.ts.map +1 -0
- package/dist/evolution/release.js +55 -0
- package/dist/evolution/release.js.map +1 -0
- package/dist/evolution/run.d.ts +88 -0
- package/dist/evolution/run.d.ts.map +1 -0
- package/dist/evolution/run.js +258 -0
- package/dist/evolution/run.js.map +1 -0
- package/dist/evolution/schedule.d.ts +59 -0
- package/dist/evolution/schedule.d.ts.map +1 -0
- package/dist/evolution/schedule.js +77 -0
- package/dist/evolution/schedule.js.map +1 -0
- package/dist/evolution/types.d.ts +174 -0
- package/dist/evolution/types.d.ts.map +1 -0
- package/dist/evolution/types.js +8 -0
- package/dist/evolution/types.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/learn/index.d.ts +27 -0
- package/dist/learn/index.d.ts.map +1 -0
- package/dist/learn/index.js +196 -0
- package/dist/learn/index.js.map +1 -0
- package/dist/report/markdown.d.ts +16 -0
- package/dist/report/markdown.d.ts.map +1 -0
- package/dist/report/markdown.js +488 -0
- package/dist/report/markdown.js.map +1 -0
- package/dist/snapshot/index.d.ts +55 -0
- package/dist/snapshot/index.d.ts.map +1 -0
- package/dist/snapshot/index.js +76 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/store/index.d.ts +31 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +69 -0
- package/dist/store/index.js.map +1 -0
- package/dist/types.d.ts +287 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/util/glob.d.ts +11 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +86 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/project.d.ts +90 -0
- package/dist/util/project.d.ts.map +1 -0
- package/dist/util/project.js +636 -0
- package/dist/util/project.js.map +1 -0
- package/dist/util/yaml.d.ts +28 -0
- package/dist/util/yaml.d.ts.map +1 -0
- package/dist/util/yaml.js +48 -0
- package/dist/util/yaml.js.map +1 -0
- package/package.json +94 -0
- package/rules/core/architecture.yaml +190 -0
- package/rules/core/cicd.yaml +212 -0
- package/rules/core/code-quality.yaml +261 -0
- package/rules/core/dependencies.yaml +132 -0
- package/rules/core/documentation.yaml +119 -0
- package/rules/core/future-readiness.yaml +91 -0
- package/rules/core/release.yaml +131 -0
- package/rules/core/repo.yaml +313 -0
- package/rules/core/security.yaml +496 -0
- package/rules/core/supply-chain.yaml +357 -0
- package/rules/core/testing.yaml +266 -0
- package/rules/detectors.yaml +2028 -0
- package/rules/index.yaml +42 -0
- package/rules/profiles/maturity.yaml +135 -0
- package/rules/stacks/ai-era.yaml +193 -0
- package/rules/stacks/api-backend.yaml +121 -0
- package/rules/stacks/cli.yaml +105 -0
- package/rules/stacks/compliance.yaml +157 -0
- package/rules/stacks/containers.yaml +124 -0
- package/rules/stacks/data.yaml +165 -0
- package/rules/stacks/go.yaml +134 -0
- package/rules/stacks/iac.yaml +128 -0
- package/rules/stacks/jvm.yaml +150 -0
- package/rules/stacks/ml-ai.yaml +140 -0
- package/rules/stacks/mobile.yaml +121 -0
- package/rules/stacks/node-typescript.yaml +166 -0
- package/rules/stacks/python.yaml +175 -0
- package/rules/stacks/rust.yaml +129 -0
- package/rules/stacks/solidity.yaml +139 -0
- package/rules/stacks/swift.yaml +100 -0
- package/rules/stacks/web-frontend.yaml +159 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
id: core/code-quality
|
|
2
|
+
title: Code Quality
|
|
3
|
+
section: S5
|
|
4
|
+
section_title: Code Quality
|
|
5
|
+
description: >
|
|
6
|
+
Linting, typing, error handling, and logging hygiene. These are the rules
|
|
7
|
+
an agent should be able to settle without asking a human — most of them are
|
|
8
|
+
answered by looking for a config file.
|
|
9
|
+
version: '1.0'
|
|
10
|
+
|
|
11
|
+
rules:
|
|
12
|
+
- id: CQ-001
|
|
13
|
+
title: A linter is configured
|
|
14
|
+
section: S5
|
|
15
|
+
section_title: Code Quality
|
|
16
|
+
severity: MEDIUM
|
|
17
|
+
class: maintainability
|
|
18
|
+
check:
|
|
19
|
+
kind: any_file
|
|
20
|
+
patterns:
|
|
21
|
+
- '.eslintrc*'
|
|
22
|
+
- 'eslint.config.*'
|
|
23
|
+
- 'biome.json*'
|
|
24
|
+
- '.ruff.toml'
|
|
25
|
+
- 'ruff.toml'
|
|
26
|
+
- '.flake8'
|
|
27
|
+
- 'setup.cfg'
|
|
28
|
+
- '.pylintrc'
|
|
29
|
+
- 'pyproject.toml'
|
|
30
|
+
- '.golangci*'
|
|
31
|
+
- 'clippy.toml'
|
|
32
|
+
- '.rustfmt.toml'
|
|
33
|
+
- 'rustfmt.toml'
|
|
34
|
+
- '.rubocop.yml'
|
|
35
|
+
- 'phpcs.xml*'
|
|
36
|
+
- 'detekt.yml'
|
|
37
|
+
- '.swiftlint.yml'
|
|
38
|
+
why: 'Style arguments in review are a tax on every pull request. Automate them and argue about design instead.'
|
|
39
|
+
remediation: 'Add the standard linter for your stack, start with its recommended config, fix what it finds.'
|
|
40
|
+
references: ['NIST-SSDF-PW.7']
|
|
41
|
+
|
|
42
|
+
- id: CQ-002
|
|
43
|
+
title: A formatter is configured
|
|
44
|
+
section: S5
|
|
45
|
+
section_title: Code Quality
|
|
46
|
+
severity: LOW
|
|
47
|
+
class: style
|
|
48
|
+
check:
|
|
49
|
+
kind: any_file
|
|
50
|
+
patterns:
|
|
51
|
+
[
|
|
52
|
+
'.prettierrc*',
|
|
53
|
+
'prettier.config.*',
|
|
54
|
+
'biome.json*',
|
|
55
|
+
'.editorconfig',
|
|
56
|
+
'.rustfmt.toml',
|
|
57
|
+
'rustfmt.toml',
|
|
58
|
+
'.clang-format',
|
|
59
|
+
'pyproject.toml',
|
|
60
|
+
'.gofmt*',
|
|
61
|
+
]
|
|
62
|
+
why: 'Formatting diffs hide real changes. Let a tool own it.'
|
|
63
|
+
remediation: 'Prettier/Black/gofmt/rustfmt — pick the default config and stop discussing it.'
|
|
64
|
+
references: ['NIST-SSDF-PW.7']
|
|
65
|
+
|
|
66
|
+
- id: CQ-003
|
|
67
|
+
title: Type checking is enabled and strict
|
|
68
|
+
section: S5
|
|
69
|
+
section_title: Code Quality
|
|
70
|
+
severity: MEDIUM
|
|
71
|
+
class: correctness
|
|
72
|
+
applies_when:
|
|
73
|
+
any:
|
|
74
|
+
- { fact: 'lang:typescript' }
|
|
75
|
+
- { fact: 'lang:python' }
|
|
76
|
+
check:
|
|
77
|
+
kind: grep_present
|
|
78
|
+
pattern: '("strict"\s*:\s*true|strict\s*=\s*true|\[tool\.mypy\]|\[tool\.pyright\]|noImplicitAny|disallow_untyped_defs)'
|
|
79
|
+
include:
|
|
80
|
+
[
|
|
81
|
+
'tsconfig.json',
|
|
82
|
+
'tsconfig.*.json',
|
|
83
|
+
'pyproject.toml',
|
|
84
|
+
'setup.cfg',
|
|
85
|
+
'mypy.ini',
|
|
86
|
+
'.mypy.ini',
|
|
87
|
+
'pyrightconfig.json',
|
|
88
|
+
]
|
|
89
|
+
flags: i
|
|
90
|
+
why: 'Types are the cheapest tests you will ever write. Lenient mode is types with the batteries removed.'
|
|
91
|
+
remediation: 'TypeScript: "strict": true. Python: mypy or pyright with strict settings on new modules.'
|
|
92
|
+
references: ['ISO-5055']
|
|
93
|
+
|
|
94
|
+
- id: CQ-004
|
|
95
|
+
title: Type escapes are not used as a default
|
|
96
|
+
section: S5
|
|
97
|
+
section_title: Code Quality
|
|
98
|
+
severity: LOW
|
|
99
|
+
class: maintainability
|
|
100
|
+
applies_when: { fact: 'lang:typescript' }
|
|
101
|
+
check:
|
|
102
|
+
kind: grep_absent
|
|
103
|
+
pattern: '(@ts-ignore|@ts-expect-error|:\s*any\b|\bas any\b|as unknown as)'
|
|
104
|
+
include: ['**/*.{ts,tsx}']
|
|
105
|
+
exclude: ['**/*.test.*', '**/*.spec.*', '**/*.d.ts']
|
|
106
|
+
why: 'Every `any` is a place the type system was told to stop helping. A few are fine; a pattern is a problem.'
|
|
107
|
+
remediation: 'Type the boundary properly, or narrow with a type guard. Delete stale @ts-ignore comments.'
|
|
108
|
+
references: ['ISO-5055']
|
|
109
|
+
|
|
110
|
+
- id: CQ-005
|
|
111
|
+
title: Errors are handled, not swallowed
|
|
112
|
+
section: S5
|
|
113
|
+
section_title: Code Quality
|
|
114
|
+
severity: HIGH
|
|
115
|
+
class: correctness
|
|
116
|
+
check:
|
|
117
|
+
kind: grep_absent
|
|
118
|
+
pattern: '(catch\s*\(\s*\w*\s*\)\s*\{\s*\}|except\s*:\s*(pass|\.\.\.)\s*$|catch\s*\{\s*\}|rescue\s*\n\s*end)'
|
|
119
|
+
include: ['**/*.{ts,tsx,js,jsx,mjs,cjs,py,go,rs,java,kt,rb,php,cs}']
|
|
120
|
+
exclude: ['**/*.test.*', '**/*.spec.*']
|
|
121
|
+
flags: i
|
|
122
|
+
why: 'An empty catch block converts a failure into a mystery. The bug report you get six weeks later will be useless.'
|
|
123
|
+
remediation: 'Log with context and either handle it or re-throw. If it is genuinely ignorable, say why in a comment.'
|
|
124
|
+
references: ['CWE-390', 'ASVS-7.4.1']
|
|
125
|
+
|
|
126
|
+
- id: CQ-006
|
|
127
|
+
title: There is a central error handler
|
|
128
|
+
section: S5
|
|
129
|
+
section_title: Code Quality
|
|
130
|
+
severity: MEDIUM
|
|
131
|
+
class: correctness
|
|
132
|
+
applies_when:
|
|
133
|
+
any:
|
|
134
|
+
- { fact: 'platform:server' }
|
|
135
|
+
- { fact: 'platform:web' }
|
|
136
|
+
check:
|
|
137
|
+
kind: grep_present
|
|
138
|
+
pattern: '(ErrorBoundary|errorHandler|error_handler|@ControllerAdvice|ExceptionHandler|app\.use\(\s*\(\s*err|onerror|useErrorBoundary|Sentry\.(captureException|init))'
|
|
139
|
+
include: ['**/*.{ts,tsx,js,jsx,py,go,rs,java,kt,rb,php}']
|
|
140
|
+
exclude: ['**/*.test.*', '**/*.spec.*']
|
|
141
|
+
why: 'Without a top-level handler, an unhandled rejection is a white screen or a dropped request.'
|
|
142
|
+
remediation: 'Add a framework-level error handler and an ErrorBoundary (React); report to your error tracker.'
|
|
143
|
+
references: ['ASVS-7.4.1']
|
|
144
|
+
|
|
145
|
+
- id: CQ-007
|
|
146
|
+
title: Logging is structured and levelled
|
|
147
|
+
section: S5
|
|
148
|
+
section_title: Code Quality
|
|
149
|
+
severity: LOW
|
|
150
|
+
class: operations
|
|
151
|
+
applies_when:
|
|
152
|
+
any:
|
|
153
|
+
- { fact: 'platform:server' }
|
|
154
|
+
- { fact: 'project:cli' }
|
|
155
|
+
check:
|
|
156
|
+
kind: manual
|
|
157
|
+
why: >-
|
|
158
|
+
Unstructured logs cannot be queried, alerted on, or correlated. At 3am, grep is not a strategy.
|
|
159
|
+
evidence: 'Sample log output: JSON or key=value, with DEBUG/INFO/WARN/ERROR used consistently.'
|
|
160
|
+
remediation: 'Emit JSON logs with a timestamp, level, message, and structured fields. Never log a bare concatenated string.'
|
|
161
|
+
references: ['OpenTelemetry-Logs', 'ASVS-7.1.1']
|
|
162
|
+
|
|
163
|
+
- id: CQ-008
|
|
164
|
+
title: Requests carry a correlation/trace ID
|
|
165
|
+
section: S5
|
|
166
|
+
section_title: Code Quality
|
|
167
|
+
severity: LOW
|
|
168
|
+
class: operations
|
|
169
|
+
applies_when: { fact: 'platform:server' }
|
|
170
|
+
check:
|
|
171
|
+
kind: grep_present
|
|
172
|
+
pattern: '(correlation[_-]?id|request[_-]?id|trace[_-]?id|x-request-id|traceId|requestId|traceContext)'
|
|
173
|
+
include: ['**/*.{ts,tsx,js,jsx,py,go,rs,java,kt}']
|
|
174
|
+
exclude: ['**/*.test.*', '**/*.spec.*']
|
|
175
|
+
flags: i
|
|
176
|
+
why: 'Without a request ID, debugging a production incident means grepping 40 million lines and praying.'
|
|
177
|
+
remediation: 'Generate an ID per request, put it in every log line and in the response header.'
|
|
178
|
+
references: ['OpenTelemetry', 'W3C-Trace-Context']
|
|
179
|
+
|
|
180
|
+
- id: CQ-009
|
|
181
|
+
title: Debug statements are not left in production paths
|
|
182
|
+
section: S5
|
|
183
|
+
section_title: Code Quality
|
|
184
|
+
severity: LOW
|
|
185
|
+
class: style
|
|
186
|
+
applies_when:
|
|
187
|
+
not: { fact: 'project:cli' }
|
|
188
|
+
check:
|
|
189
|
+
kind: grep_absent
|
|
190
|
+
pattern: '(console\.(log|debug|info)\s*\(|print\s*\(\s*[''"]DEBUG|pdb\.set_trace|debugger\s*;|var_dump\s*\()'
|
|
191
|
+
include: ['**/*.{ts,tsx,js,jsx,mjs,cjs,py,php,rb,go,rs,java,kt}']
|
|
192
|
+
exclude: ['**/*.test.*', '**/*.spec.*', '**/scripts/**', '**/tools/**', '**/debug/**']
|
|
193
|
+
why: 'Stray debug output is noise at best and a data leak at worst.'
|
|
194
|
+
remediation: 'Use the project logger, or delete the line. Add a lint rule to keep it out.'
|
|
195
|
+
references: ['CWE-532']
|
|
196
|
+
|
|
197
|
+
- id: CQ-010
|
|
198
|
+
title: TODO/FIXME debt is tracked, not just annotated
|
|
199
|
+
section: S5
|
|
200
|
+
section_title: Code Quality
|
|
201
|
+
severity: LOW
|
|
202
|
+
class: maintainability
|
|
203
|
+
check:
|
|
204
|
+
kind: grep_wrong
|
|
205
|
+
pattern: '(TODO|FIXME|XXX|HACK|WORKAROUND)\b'
|
|
206
|
+
include: ['**/*.{ts,tsx,js,jsx,py,go,rs,java,kt,rb,php,cs,yml,yaml}']
|
|
207
|
+
exclude: ['**/*.md', '**/docs/**', '**/node_modules/**']
|
|
208
|
+
why: 'A TODO with no owner and no ticket is a lie the codebase tells itself.'
|
|
209
|
+
remediation: 'Convert each one to a tracked issue with a link in the comment, or delete it if it no longer applies.'
|
|
210
|
+
|
|
211
|
+
- id: CQ-011
|
|
212
|
+
title: Functions do one thing
|
|
213
|
+
section: S5
|
|
214
|
+
section_title: Code Quality
|
|
215
|
+
severity: LOW
|
|
216
|
+
class: maintainability
|
|
217
|
+
depths: [deep]
|
|
218
|
+
check: { kind: manual }
|
|
219
|
+
why: >-
|
|
220
|
+
A function that needs "and" to describe is two functions. Long functions hide branches nobody tests.
|
|
221
|
+
evidence: 'Three representative functions over ~60 lines: can each be described in one sentence?'
|
|
222
|
+
remediation: 'Extract until each function reads as a single step at the current level of abstraction.'
|
|
223
|
+
references: ['Clean-Code', 'ISO-5055']
|
|
224
|
+
|
|
225
|
+
- id: CQ-012
|
|
226
|
+
title: Duplicated logic has been consolidated
|
|
227
|
+
section: S5
|
|
228
|
+
section_title: Code Quality
|
|
229
|
+
severity: MEDIUM
|
|
230
|
+
class: maintainability
|
|
231
|
+
depths: [deep]
|
|
232
|
+
check: { kind: manual }
|
|
233
|
+
evidence: 'Output of a duplication checker (jscpd, PMD CPD, sonar) — and the top three duplicates by size.'
|
|
234
|
+
why: 'Every copy is a place a bug fix will not reach.'
|
|
235
|
+
remediation: 'Extract the shared logic; accept duplication only when the two copies are expected to diverge.'
|
|
236
|
+
references: ['ISO-5055', 'Anti-pattern:Shotgun-Surgery']
|
|
237
|
+
|
|
238
|
+
- id: CQ-013
|
|
239
|
+
title: Complexity is measured
|
|
240
|
+
section: S5
|
|
241
|
+
section_title: Code Quality
|
|
242
|
+
severity: FUTURE
|
|
243
|
+
class: maintainability
|
|
244
|
+
depths: [deep]
|
|
245
|
+
check:
|
|
246
|
+
kind: grep_present
|
|
247
|
+
pattern: '(complexity|cyclomatic|radon|gocyclo|cognitive)'
|
|
248
|
+
include:
|
|
249
|
+
[
|
|
250
|
+
'**/.eslintrc*',
|
|
251
|
+
'eslint.config.*',
|
|
252
|
+
'pyproject.toml',
|
|
253
|
+
'.ruff.toml',
|
|
254
|
+
'setup.cfg',
|
|
255
|
+
'.golangci*',
|
|
256
|
+
'sonar-project.properties',
|
|
257
|
+
]
|
|
258
|
+
flags: i
|
|
259
|
+
why: 'You cannot argue about complexity without a number.'
|
|
260
|
+
remediation: 'Enable an eslint complexity rule (≤10) or radon/gocyclo; report rather than hard-fail at first.'
|
|
261
|
+
references: ['ISO-5055']
|
|
@@ -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
|
+
USA 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. USA 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']
|