@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,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']
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
id: core/repo
|
|
2
|
+
title: Repository & Project Structure
|
|
3
|
+
section: S1
|
|
4
|
+
section_title: Repository & Project Structure
|
|
5
|
+
description: >
|
|
6
|
+
Root hygiene, the essential-files baseline, and version-control quality.
|
|
7
|
+
Cheap to fix, expensive to ignore — this is where most leaked credentials
|
|
8
|
+
and most onboarding pain originate.
|
|
9
|
+
version: '1.0'
|
|
10
|
+
|
|
11
|
+
rules:
|
|
12
|
+
- id: REPO-001
|
|
13
|
+
title: .gitignore is present
|
|
14
|
+
section: S1
|
|
15
|
+
section_title: Repository & Project Structure
|
|
16
|
+
severity: CRITICAL
|
|
17
|
+
class: security
|
|
18
|
+
check: { kind: file_exists, files: ['.gitignore'] }
|
|
19
|
+
why: >
|
|
20
|
+
Without a .gitignore the next `git add -A` commits node_modules, build
|
|
21
|
+
output, and — sooner or later — a .env file.
|
|
22
|
+
remediation: 'Add a .gitignore for your stack (github/gitignore has templates).'
|
|
23
|
+
references: ['CWE-540', 'OpenSSF-Scorecard:Binary-Artifacts']
|
|
24
|
+
|
|
25
|
+
- id: REPO-002
|
|
26
|
+
title: No environment/secret files committed
|
|
27
|
+
section: S1
|
|
28
|
+
section_title: Repository & Project Structure
|
|
29
|
+
severity: CRITICAL
|
|
30
|
+
class: security
|
|
31
|
+
check:
|
|
32
|
+
kind: tracked_absent
|
|
33
|
+
patterns:
|
|
34
|
+
[
|
|
35
|
+
'.env',
|
|
36
|
+
'.env.*',
|
|
37
|
+
'*.env',
|
|
38
|
+
'*.pem',
|
|
39
|
+
'*.key',
|
|
40
|
+
'*.p12',
|
|
41
|
+
'*.pfx',
|
|
42
|
+
'id_rsa*',
|
|
43
|
+
'credentials*',
|
|
44
|
+
'secrets/**',
|
|
45
|
+
'.npmrc',
|
|
46
|
+
'.pypirc',
|
|
47
|
+
]
|
|
48
|
+
why: 'A committed .env is a published credential. Rotating is the only fix.'
|
|
49
|
+
remediation: 'Remove from the index, rotate every value in the file, purge history (git filter-repo / BFG), add to .gitignore.'
|
|
50
|
+
references: ['CWE-798', 'ASVS-14.3.2', 'OpenSSF-Scorecard:Binary-Artifacts']
|
|
51
|
+
|
|
52
|
+
- id: REPO-003
|
|
53
|
+
title: No secrets in git history
|
|
54
|
+
section: S1
|
|
55
|
+
section_title: Repository & Project Structure
|
|
56
|
+
severity: CRITICAL
|
|
57
|
+
class: security
|
|
58
|
+
check:
|
|
59
|
+
kind: command
|
|
60
|
+
# NOTE: stage 1 allows one optional quote: most real secrets in history
|
|
61
|
+
# are quoted (`"token": "abc…"`, `key = "abc…"`), and a rule blind to
|
|
62
|
+
# them is decorative. Stage 2 drops only unquoted type-annotation
|
|
63
|
+
# shapes (`privateKey: NIOSSLPrivateKey`, `token: String`) — a bare
|
|
64
|
+
# capitalized identifier after a colon is a type, not a value. Exit
|
|
65
|
+
# algebra: the first grep runs WITHOUT -q so lines flow; only the
|
|
66
|
+
# final grep is quiet (matches must never reach CI logs). -v exits 1
|
|
67
|
+
# (→ PASS) only when every match was a declaration; any other hit
|
|
68
|
+
# exits 0 (→ FAIL). Quoted values and `=` assignments are never
|
|
69
|
+
# excluded — recall first for a CRITICAL history scan.
|
|
70
|
+
run: '! git log -p --all | grep -iE "(api[_-]?key|secret|password|passwd|token|private[_-]?key)[[:space:]]*[:=][[:space:]]*[\"'']?[A-Za-z0-9/+_-]{16,}" | grep -qiEv "(api[_-]?key|secret|password|passwd|token|private[_-]?key)[[:space:]]*:[[:space:]]*[A-Z][A-Za-z0-9_]*[[:space:]]*[,);]*[[:space:]]*\{?[[:space:]]*$"'
|
|
71
|
+
expect_exit: 0
|
|
72
|
+
why: 'Deleting a secret from HEAD does not delete it from history. Anyone who cloned the repo still has it.'
|
|
73
|
+
evidence: 'Command output, or a manual `gitleaks detect --log-opts=--all` run.'
|
|
74
|
+
remediation: 'Rotate the exposed values and rewrite history with git-filter-repo. Rotation first: assume it is already public.'
|
|
75
|
+
references: ['CWE-798', 'ASVS-14.3.2']
|
|
76
|
+
|
|
77
|
+
- id: REPO-004
|
|
78
|
+
title: README present
|
|
79
|
+
section: S1
|
|
80
|
+
section_title: Repository & Project Structure
|
|
81
|
+
severity: HIGH
|
|
82
|
+
class: documentation
|
|
83
|
+
check:
|
|
84
|
+
kind: any_file
|
|
85
|
+
patterns: ['README.md', 'readme.md', 'README.rst', 'README.txt', 'README']
|
|
86
|
+
why: 'The README is the front door. Without it, every new contributor needs a human guided tour.'
|
|
87
|
+
remediation: 'Write: what this is, how to install, how to run it, how to contribute. Four headings, one page.'
|
|
88
|
+
references: ['CII-Best-Practices']
|
|
89
|
+
|
|
90
|
+
- id: REPO-005
|
|
91
|
+
title: LICENSE present
|
|
92
|
+
section: S1
|
|
93
|
+
section_title: Repository & Project Structure
|
|
94
|
+
severity: HIGH
|
|
95
|
+
class: compliance
|
|
96
|
+
check:
|
|
97
|
+
kind: any_file
|
|
98
|
+
patterns: ['LICENSE*', 'COPYING*']
|
|
99
|
+
why: 'No license means "all rights reserved" by default. Nobody can legally use it, including you, later.'
|
|
100
|
+
remediation: 'Add MIT / Apache-2.0 / GPL-3.0 as appropriate. Choose at choosealicense.com.'
|
|
101
|
+
references: ['OpenSSF-Scorecard:License', 'SPDX']
|
|
102
|
+
|
|
103
|
+
- id: REPO-006
|
|
104
|
+
title: .env.example documents required configuration
|
|
105
|
+
section: S1
|
|
106
|
+
section_title: Repository & Project Structure
|
|
107
|
+
severity: HIGH
|
|
108
|
+
class: maintainability
|
|
109
|
+
applies_when:
|
|
110
|
+
any:
|
|
111
|
+
- { fact: 'has:database' }
|
|
112
|
+
- { fact: 'platform:server' }
|
|
113
|
+
- { fact: 'auth:jwt' }
|
|
114
|
+
- { fact: 'auth:apikey' }
|
|
115
|
+
- { fact: 'auth:oauth' }
|
|
116
|
+
check:
|
|
117
|
+
kind: any_file
|
|
118
|
+
patterns: ['.env.example', '.env.sample', '.env.template', 'env.example', 'config.example.*']
|
|
119
|
+
why: 'Undocumented required env vars turn setup into archaeology.'
|
|
120
|
+
remediation: 'Add .env.example listing every variable the app reads, with safe placeholder values and a comment per var.'
|
|
121
|
+
references: ['ASVS-14.3.2']
|
|
122
|
+
|
|
123
|
+
- id: REPO-007
|
|
124
|
+
title: Build artifacts and dependencies are not committed
|
|
125
|
+
section: S1
|
|
126
|
+
section_title: Repository & Project Structure
|
|
127
|
+
severity: HIGH
|
|
128
|
+
class: maintainability
|
|
129
|
+
check:
|
|
130
|
+
kind: tracked_absent
|
|
131
|
+
patterns:
|
|
132
|
+
[
|
|
133
|
+
'dist/**',
|
|
134
|
+
'build/**',
|
|
135
|
+
'out/**',
|
|
136
|
+
'node_modules/**',
|
|
137
|
+
'target/**',
|
|
138
|
+
'.venv/**',
|
|
139
|
+
'venv/**',
|
|
140
|
+
'*.egg-info/**',
|
|
141
|
+
'__pycache__/**',
|
|
142
|
+
'coverage/**',
|
|
143
|
+
'.next/**',
|
|
144
|
+
]
|
|
145
|
+
why: 'Committed build output bloats the repo, guarantees merge conflicts, and hides the real source in review noise.'
|
|
146
|
+
remediation: 'Untrack (git rm -r --cached) and add the paths to .gitignore.'
|
|
147
|
+
references: ['OpenSSF-Scorecard:Binary-Artifacts']
|
|
148
|
+
|
|
149
|
+
- id: REPO-008
|
|
150
|
+
title: Large binaries are not committed directly
|
|
151
|
+
section: S1
|
|
152
|
+
section_title: Repository & Project Structure
|
|
153
|
+
severity: MEDIUM
|
|
154
|
+
class: maintainability
|
|
155
|
+
check:
|
|
156
|
+
kind: tracked_absent
|
|
157
|
+
patterns:
|
|
158
|
+
[
|
|
159
|
+
'*.mp4',
|
|
160
|
+
'*.mov',
|
|
161
|
+
'*.zip',
|
|
162
|
+
'*.tar.gz',
|
|
163
|
+
'*.tgz',
|
|
164
|
+
'*.exe',
|
|
165
|
+
'*.dll',
|
|
166
|
+
'*.so',
|
|
167
|
+
'*.dylib',
|
|
168
|
+
'*.jar',
|
|
169
|
+
'*.war',
|
|
170
|
+
'*.psd',
|
|
171
|
+
'*.sketch',
|
|
172
|
+
]
|
|
173
|
+
why: 'Git stores every revision of every binary forever. Use Git LFS or object storage.'
|
|
174
|
+
remediation: 'Move binaries to LFS or object storage; rewrite history if the repo has already grown past ~200 MB.'
|
|
175
|
+
references: ['OpenSSF-Scorecard:Binary-Artifacts']
|
|
176
|
+
|
|
177
|
+
- id: REPO-009
|
|
178
|
+
title: SECURITY.md published
|
|
179
|
+
section: S1
|
|
180
|
+
section_title: Repository & Project Structure
|
|
181
|
+
severity: HIGH
|
|
182
|
+
class: security
|
|
183
|
+
applies_when:
|
|
184
|
+
not: { fact: 'maturity:prototype' }
|
|
185
|
+
check:
|
|
186
|
+
kind: any_file
|
|
187
|
+
patterns: ['SECURITY.md', '.github/SECURITY.md', 'docs/SECURITY.md']
|
|
188
|
+
why: 'Without a disclosure route, researchers either stay silent or post publicly. Neither helps you.'
|
|
189
|
+
remediation: 'Add SECURITY.md with supported versions and a report address. GitHub surfaces it in the Security tab.'
|
|
190
|
+
references: ['OpenSSF-Scorecard:Security-Policy', 'NIST-SSDF-RV.1.1']
|
|
191
|
+
|
|
192
|
+
- id: REPO-010
|
|
193
|
+
title: CHANGELOG maintained
|
|
194
|
+
section: S1
|
|
195
|
+
section_title: Repository & Project Structure
|
|
196
|
+
severity: MEDIUM
|
|
197
|
+
class: documentation
|
|
198
|
+
applies_when:
|
|
199
|
+
not: { fact: 'maturity:prototype' }
|
|
200
|
+
check:
|
|
201
|
+
kind: any_file
|
|
202
|
+
patterns: ['CHANGELOG*', 'CHANGES*', 'HISTORY.md']
|
|
203
|
+
why: 'Users and downstream maintainers need to know what changed and whether it will break them.'
|
|
204
|
+
remediation: 'Adopt Keep a Changelog, or generate it from Conventional Commits / Changesets.'
|
|
205
|
+
references: ['Keep-a-Changelog']
|
|
206
|
+
|
|
207
|
+
- id: REPO-011
|
|
208
|
+
title: CONTRIBUTING guide present
|
|
209
|
+
section: S1
|
|
210
|
+
section_title: Repository & Project Structure
|
|
211
|
+
severity: LOW
|
|
212
|
+
class: documentation
|
|
213
|
+
applies_when:
|
|
214
|
+
not: { fact: 'maturity:prototype' }
|
|
215
|
+
check: { kind: any_file, patterns: ['CONTRIBUTING*', 'docs/CONTRIBUTING*'] }
|
|
216
|
+
why: 'Turns "how do I run the tests?" from an interruption into a link.'
|
|
217
|
+
remediation: 'Setup, test/lint commands, branch naming, commit convention, review expectations.'
|
|
218
|
+
references: ['CII-Best-Practices']
|
|
219
|
+
|
|
220
|
+
- id: REPO-012
|
|
221
|
+
title: Code of conduct present
|
|
222
|
+
section: S1
|
|
223
|
+
section_title: Repository & Project Structure
|
|
224
|
+
severity: LOW
|
|
225
|
+
class: compliance
|
|
226
|
+
applies_when:
|
|
227
|
+
not: { fact: 'maturity:prototype' }
|
|
228
|
+
check: { kind: any_file, patterns: ['CODE_OF_CONDUCT*', 'docs/CODE_OF_CONDUCT*'] }
|
|
229
|
+
why: 'Sets the floor for interaction and gives maintainers something to point at.'
|
|
230
|
+
remediation: 'Adopt the Contributor Covenant.'
|
|
231
|
+
references: ['CII-Best-Practices']
|
|
232
|
+
|
|
233
|
+
- id: REPO-013
|
|
234
|
+
title: .editorconfig present
|
|
235
|
+
section: S1
|
|
236
|
+
section_title: Repository & Project Structure
|
|
237
|
+
severity: LOW
|
|
238
|
+
class: style
|
|
239
|
+
check: { kind: file_exists, files: ['.editorconfig'] }
|
|
240
|
+
why: 'Kills tabs-vs-spaces diffs before they start, across every editor.'
|
|
241
|
+
remediation: 'Add a 6-line .editorconfig (charset, EOL, indent style/size, trailing whitespace, final newline).'
|
|
242
|
+
|
|
243
|
+
- id: REPO-014
|
|
244
|
+
title: CODEOWNERS assigns review responsibility
|
|
245
|
+
section: S1
|
|
246
|
+
section_title: Repository & Project Structure
|
|
247
|
+
severity: MEDIUM
|
|
248
|
+
class: operations
|
|
249
|
+
applies_when: { fact: 'metric:contributors', op: 'gt', value: 2 }
|
|
250
|
+
check: { kind: any_file, patterns: ['.github/CODEOWNERS', 'CODEOWNERS', 'docs/CODEOWNERS'] }
|
|
251
|
+
why: 'With more than two contributors, unreviewed-by-default becomes the default.'
|
|
252
|
+
remediation: 'Add .github/CODEOWNERS mapping paths to teams; require review from code owners on the default branch.'
|
|
253
|
+
references: ['OpenSSF-Scorecard:Code-Review']
|
|
254
|
+
|
|
255
|
+
- id: REPO-015
|
|
256
|
+
title: Commit history is meaningful
|
|
257
|
+
section: S1
|
|
258
|
+
section_title: Repository & Project Structure
|
|
259
|
+
severity: LOW
|
|
260
|
+
class: maintainability
|
|
261
|
+
check: { kind: manual }
|
|
262
|
+
why: >-
|
|
263
|
+
Commit messages are the only history most projects ever write down. "fix stuff" costs the next person an afternoon.
|
|
264
|
+
evidence: 'Last 20 commit messages. Are they descriptive and consistently formatted?'
|
|
265
|
+
remediation: 'Adopt Conventional Commits; enforce with commitlint in CI.'
|
|
266
|
+
|
|
267
|
+
- id: REPO-016
|
|
268
|
+
title: Branch strategy is defined and stale branches pruned
|
|
269
|
+
section: S1
|
|
270
|
+
section_title: Repository & Project Structure
|
|
271
|
+
severity: LOW
|
|
272
|
+
class: maintainability
|
|
273
|
+
applies_when: { fact: 'metric:branches', op: 'gt', value: 3 }
|
|
274
|
+
check: { kind: manual }
|
|
275
|
+
why: >-
|
|
276
|
+
A branching strategy nobody wrote down is a branching strategy nobody follows, and stale branches hide work.
|
|
277
|
+
evidence: 'Branch list and age of the oldest non-default branch.'
|
|
278
|
+
remediation: 'Document trunk-based or Git Flow in CONTRIBUTING; delete merged branches; protect the default branch.'
|
|
279
|
+
|
|
280
|
+
- id: REPO-017
|
|
281
|
+
title: Concern separation at the root
|
|
282
|
+
section: S1
|
|
283
|
+
section_title: Repository & Project Structure
|
|
284
|
+
severity: MEDIUM
|
|
285
|
+
class: maintainability
|
|
286
|
+
check:
|
|
287
|
+
kind: any_file
|
|
288
|
+
patterns: ['src/**', 'app/**', 'lib/**', 'pkg/**', 'internal/**', 'packages/**']
|
|
289
|
+
why: 'A flat root of 40 files makes ownership and navigation guesswork.'
|
|
290
|
+
remediation: 'Group by concern (src/, tests/, docs/, scripts/, config/). Monorepos: packages/ or apps/.'
|
|
291
|
+
|
|
292
|
+
- id: REPO-018
|
|
293
|
+
title: Agent instruction file present (AGENTS.md / CLAUDE.md)
|
|
294
|
+
section: S1
|
|
295
|
+
section_title: Repository & Project Structure
|
|
296
|
+
severity: LOW
|
|
297
|
+
class: documentation
|
|
298
|
+
check:
|
|
299
|
+
kind: any_file
|
|
300
|
+
patterns:
|
|
301
|
+
[
|
|
302
|
+
'AGENTS.md',
|
|
303
|
+
'CLAUDE.md',
|
|
304
|
+
'.cursorrules',
|
|
305
|
+
'.github/copilot-instructions.md',
|
|
306
|
+
'codex.md',
|
|
307
|
+
'.windsurfrules',
|
|
308
|
+
]
|
|
309
|
+
why: >
|
|
310
|
+
Coding agents perform measurably better when the repo tells them how to
|
|
311
|
+
build, test, and what not to touch. It also stops them inventing commands.
|
|
312
|
+
remediation: 'Add AGENTS.md: setup, build/test/lint commands, conventions, and explicit no-go areas.'
|
|
313
|
+
references: ['Agent-Skills']
|