@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.
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/USAT.md +596 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +438 -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 +72 -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 +21 -0
- package/dist/engine/audit.d.ts.map +1 -0
- package/dist/engine/audit.js +295 -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 +22 -0
- package/dist/engine/loader.d.ts.map +1 -0
- package/dist/engine/loader.js +360 -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/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/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/types.d.ts +282 -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 +72 -0
- package/dist/util/project.d.ts.map +1 -0
- package/dist/util/project.js +586 -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/docs/ARCHITECTURE.md +119 -0
- package/docs/README.md +27 -0
- package/docs/adr/0001-record-architecture-decisions.md +35 -0
- package/docs/adr/0002-typescript-engine-over-python.md +49 -0
- package/docs/adr/0003-rules-are-data-not-code.md +50 -0
- package/docs/adr/0004-markdown-only-output.md +41 -0
- package/docs/adr/0005-maturity-dampens-severity.md +56 -0
- package/docs/adr/0006-severity-status-two-axes.md +48 -0
- package/docs/adr/0007-suppressions-are-visible-and-expiring.md +46 -0
- package/docs/adr/0008-report-trailer-and-diff.md +48 -0
- package/docs/adr/0009-fail-closed-on-malformed-input.md +56 -0
- package/docs/adr/0010-detector-design.md +54 -0
- package/docs/adr/0011-coexist-with-deep-scanners.md +52 -0
- package/docs/adr/README.md +32 -0
- package/docs/agent-integration.md +129 -0
- package/docs/ci-integration.md +163 -0
- package/docs/concepts.md +196 -0
- package/docs/configuration.md +105 -0
- package/docs/detectors.md +186 -0
- package/docs/getting-started.md +99 -0
- package/docs/maturity-profiles.md +156 -0
- package/docs/reference/api.md +193 -0
- package/docs/reference/cli.md +412 -0
- package/docs/rule-packs.md +278 -0
- package/docs/standards-mapping.md +171 -0
- package/package.json +96 -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 +303 -0
- package/rules/core/security.yaml +494 -0
- package/rules/core/supply-chain.yaml +357 -0
- package/rules/core/testing.yaml +260 -0
- package/rules/detectors.yaml +2255 -0
- package/rules/index.yaml +41 -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/web-frontend.yaml +159 -0
- package/templates/AGENTS.audit.md +135 -0
- 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']
|