@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,366 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { SEVERITY_LADDER } from './loader.js';
|
|
3
|
+
import { MAX_FILE_BYTES, MAX_FILES, Project } from '../util/project.js';
|
|
4
|
+
import { detect, loadDetectorFile } from '../detect/index.js';
|
|
5
|
+
import { loadRulePacks, applyRuleOverrides } from './loader.js';
|
|
6
|
+
import { evaluateRule, packApplies, ruleApplies } from './evaluate.js';
|
|
7
|
+
import { loadSections } from './sections.js';
|
|
8
|
+
import { loadProfiles, dampen } from './maturity.js';
|
|
9
|
+
import { loadConfig } from '../config.js';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
/** `rules/`, resolved relative to the installed package (works from src and dist). */
|
|
13
|
+
const DEFAULT_RULES_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'rules');
|
|
14
|
+
/** Version of this build, read from package.json so it never drifts. */
|
|
15
|
+
const DEFAULT_VERSION = (() => {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json'), 'utf8'));
|
|
18
|
+
return pkg.version ?? '0.0.0';
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return '0.0.0';
|
|
22
|
+
}
|
|
23
|
+
})();
|
|
24
|
+
import { score } from './score.js';
|
|
25
|
+
export function runAudit(options) {
|
|
26
|
+
// The programmatic entry point must be usable with nothing but a target, so
|
|
27
|
+
// every knob the CLI exposes gets a sane default here rather than a crash.
|
|
28
|
+
const config = options.config ?? loadConfig(options.target);
|
|
29
|
+
const opts = normalizeAuditOptions(options, config);
|
|
30
|
+
const warnings = [];
|
|
31
|
+
const project = new Project(opts.target, config.ignore ?? [], resolveLimits(options, config, warnings));
|
|
32
|
+
const git = project.gitInfo();
|
|
33
|
+
appendHistoryWarnings(git, warnings);
|
|
34
|
+
const detectors = loadDetectorFile(opts.rulesDir);
|
|
35
|
+
const detection = detect(project, detectors, git, config.facts ?? []);
|
|
36
|
+
const { packs, warnings: packWarnings } = loadRulePacks(opts.rulesDir);
|
|
37
|
+
warnings.push(...packWarnings);
|
|
38
|
+
mergeExtraPacks(packs, options.extraPacks);
|
|
39
|
+
const { disabled, overrides } = collectRuleSettings(config, warnings);
|
|
40
|
+
applyRuleOverrides(packs, overrides);
|
|
41
|
+
const suppressions = resolveSuppressions(config.suppressions, warnings);
|
|
42
|
+
const { include, exclude } = resolvePackSets(options, config);
|
|
43
|
+
// A pack may assert extra facts simply by applying (e.g. "we are a monorepo").
|
|
44
|
+
const facts = detection.facts;
|
|
45
|
+
const selection = selectInitialPacks(packs, facts, include, exclude);
|
|
46
|
+
// Packs can contribute facts, which can make another pack apply. Resolve to a
|
|
47
|
+
// fixed point (bounded, so a malformed pack cannot hang the audit).
|
|
48
|
+
resolvePackFacts(packs, facts, include, exclude, selection);
|
|
49
|
+
const sections = selectSections(loadSections(opts.rulesDir), config.sections, warnings);
|
|
50
|
+
const profiles = loadProfiles(opts.rulesDir);
|
|
51
|
+
const maturity = resolveMaturity(opts.profile, config.maturity, detection.maturity, warnings);
|
|
52
|
+
const profile = profiles[maturity];
|
|
53
|
+
const ctx = {
|
|
54
|
+
project,
|
|
55
|
+
facts,
|
|
56
|
+
depth: opts.depth,
|
|
57
|
+
allowCommands: opts.allowCommands,
|
|
58
|
+
disabled,
|
|
59
|
+
suppressions,
|
|
60
|
+
};
|
|
61
|
+
const evaluatedAll = evaluatePacks(selection.activePacks, facts, opts.depth, include, ctx, profile);
|
|
62
|
+
// A `sections:` restriction narrows both the scored set and the report, so a
|
|
63
|
+
// scoped audit cannot leak findings it promised to exclude.
|
|
64
|
+
const sectionFilter = config.sections ?? [];
|
|
65
|
+
const wanted = new Set(sections.map((s) => s.id));
|
|
66
|
+
const evaluated = sectionFilter.length > 0
|
|
67
|
+
? evaluatedAll.filter((e) => wanted.has(e.finding.section))
|
|
68
|
+
: evaluatedAll;
|
|
69
|
+
// Index warnings go last: content reads happen lazily during rule
|
|
70
|
+
// evaluation, so oversize counts are only complete once scoring is done.
|
|
71
|
+
appendIndexWarnings(project, warnings);
|
|
72
|
+
const card = score(evaluated, sections, profile);
|
|
73
|
+
const report = buildReport(opts, git, detection, facts, maturity, card, evaluated, selection.packsLoaded, selection.packsSkipped);
|
|
74
|
+
return { report, warnings, profile };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Merges an additional capability set into the loaded packs for a single run.
|
|
78
|
+
* A pack id already present in the base registry wins (the registry is the
|
|
79
|
+
* source of truth); duplicate ids from `extraPacks` are dropped silently so a
|
|
80
|
+
* released capability cannot shadow a shipped one.
|
|
81
|
+
*/
|
|
82
|
+
function mergeExtraPacks(packs, extra) {
|
|
83
|
+
if (!extra || extra.length === 0)
|
|
84
|
+
return;
|
|
85
|
+
const seen = new Set(packs.map((p) => p.id));
|
|
86
|
+
for (const p of extra) {
|
|
87
|
+
if (!seen.has(p.id)) {
|
|
88
|
+
seen.add(p.id);
|
|
89
|
+
packs.push(p);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function normalizeAuditOptions(options, config) {
|
|
94
|
+
return {
|
|
95
|
+
rulesDir: options.rulesDir ?? DEFAULT_RULES_DIR,
|
|
96
|
+
depth: options.depth ?? 'standard',
|
|
97
|
+
profile: options.profile ?? 'auto',
|
|
98
|
+
allowCommands: options.allowCommands ?? false,
|
|
99
|
+
usaVersion: options.usaVersion ?? DEFAULT_VERSION,
|
|
100
|
+
target: options.target,
|
|
101
|
+
config,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Expired (or undated) waivers fail closed: an `until` date in the past β or
|
|
106
|
+
* one that cannot be parsed β excludes the suppression and raises a warning,
|
|
107
|
+
* so an audit never silently honours dead risk acceptances.
|
|
108
|
+
*/
|
|
109
|
+
function resolveSuppressions(suppressions, warnings) {
|
|
110
|
+
const map = new Map();
|
|
111
|
+
for (const s of suppressions ?? []) {
|
|
112
|
+
if (!s.rule)
|
|
113
|
+
continue;
|
|
114
|
+
if (s.until && isSuppressionExpired(s.rule, s.until, warnings))
|
|
115
|
+
continue;
|
|
116
|
+
map.set(s.rule, s.reason);
|
|
117
|
+
}
|
|
118
|
+
return map;
|
|
119
|
+
}
|
|
120
|
+
function isSuppressionExpired(rule, until, warnings) {
|
|
121
|
+
const t = Date.parse(until);
|
|
122
|
+
if (Number.isNaN(t)) {
|
|
123
|
+
warnings.push(`suppression for ${rule} has an unparseable "until" date ("${until}") β waiver ignored`);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
if (t < Date.now()) {
|
|
127
|
+
warnings.push(`suppression for ${rule} expired on ${until} β treating as an active finding`);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const MATURITIES = ['prototype', 'mvp', 'beta', 'production', 'legacy'];
|
|
133
|
+
/**
|
|
134
|
+
* CLI --profile wins; otherwise a valid config `maturity` pins the bar;
|
|
135
|
+
* otherwise auto-detection stands. Invalid config values warn and fall back.
|
|
136
|
+
*/
|
|
137
|
+
function resolveMaturity(cliProfile, configMaturity, detected, warnings) {
|
|
138
|
+
if (cliProfile !== 'auto')
|
|
139
|
+
return cliProfile;
|
|
140
|
+
if (configMaturity === undefined)
|
|
141
|
+
return detected;
|
|
142
|
+
if (MATURITIES.includes(configMaturity))
|
|
143
|
+
return configMaturity;
|
|
144
|
+
warnings.push(`.usa.yaml: invalid maturity "${String(configMaturity)}" β using auto-detected ${detected}`);
|
|
145
|
+
return detected;
|
|
146
|
+
}
|
|
147
|
+
/** Restrict scoring and reporting to the configured sections, if any. */
|
|
148
|
+
function selectSections(all, wanted, warnings) {
|
|
149
|
+
if (!wanted || wanted.length === 0)
|
|
150
|
+
return all;
|
|
151
|
+
const known = new Set(all.map((s) => s.id));
|
|
152
|
+
for (const id of wanted) {
|
|
153
|
+
if (!known.has(id))
|
|
154
|
+
warnings.push(`.usa.yaml: unknown section "${id}" in sections β ignored`);
|
|
155
|
+
}
|
|
156
|
+
return all.filter((s) => wanted.includes(s.id));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Scale honesty: a truncated index or skipped oversize files means PASS
|
|
160
|
+
* verdicts may rest on unseen files. Loud warning, never silent absorption.
|
|
161
|
+
*/
|
|
162
|
+
function appendIndexWarnings(project, warnings) {
|
|
163
|
+
if (project.truncated) {
|
|
164
|
+
warnings.push(`index truncated at ${MAX_FILES} files β the tree is bigger than the audit can see; ` +
|
|
165
|
+
'treat PASS verdicts as partial and split the target (e.g. per-package audits)');
|
|
166
|
+
}
|
|
167
|
+
if (project.skippedLarge > 0) {
|
|
168
|
+
warnings.push(`${project.skippedLarge} file(s) skipped for exceeding ${MAX_FILE_BYTES} bytes β ` +
|
|
169
|
+
'content checks could not see them');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* CLI flags win over config file; both are validated with warnings.
|
|
174
|
+
* Invalid values fall back to engine defaults (never zero, never infinite).
|
|
175
|
+
*/
|
|
176
|
+
function resolveLimits(options, config, warnings) {
|
|
177
|
+
return {
|
|
178
|
+
maxFiles: validatedLimit(options.maxFiles ?? config.limits?.max_files, 'limits.max_files / --max-files', warnings),
|
|
179
|
+
maxBytes: validatedLimit(options.maxBytes ?? config.limits?.max_bytes, 'limits.max_bytes / --max-bytes', warnings),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function validatedLimit(v, name, warnings) {
|
|
183
|
+
if (v === undefined)
|
|
184
|
+
return undefined;
|
|
185
|
+
if (typeof v === 'number' && Number.isFinite(v) && v > 0)
|
|
186
|
+
return Math.floor(v);
|
|
187
|
+
warnings.push(`invalid ${name} "${String(v)}" (must be a positive number) β using defaults`);
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* History-thin targets blind the history-dependent rules (REPO-003 scans
|
|
192
|
+
* `git log`, REL-002 needs tags, maturity signals need commits). The
|
|
193
|
+
* negation in REPO-003 even turns git errors into PASS β true only in the
|
|
194
|
+
* vacuous sense. Say so loudly instead of scoring blind confidence.
|
|
195
|
+
*/
|
|
196
|
+
function appendHistoryWarnings(git, warnings) {
|
|
197
|
+
if (!git.isRepo) {
|
|
198
|
+
warnings.push('not a git repository β history and provenance checks cannot verify anything; ' +
|
|
199
|
+
'treat history-dependent findings as vacuous');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (git.commits <= 1) {
|
|
203
|
+
warnings.push('single-commit history (shallow clone?) β maturity signals, tag checks, and ' +
|
|
204
|
+
'history scans are under-verified; prefer a full clone for release-grade audits');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function resolvePackSets(options, config) {
|
|
208
|
+
return {
|
|
209
|
+
include: new Set(options.includePacks ?? config.include ?? []),
|
|
210
|
+
exclude: new Set(options.excludePacks ?? config.exclude ?? []),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
function collectRuleSettings(config, warnings) {
|
|
214
|
+
const disabled = new Set();
|
|
215
|
+
const overrides = {};
|
|
216
|
+
for (const [id, o] of Object.entries(config.rules ?? {})) {
|
|
217
|
+
if (o.disabled)
|
|
218
|
+
disabled.add(id);
|
|
219
|
+
const severity = validateOverrideSeverity(id, o.severity, warnings);
|
|
220
|
+
const weight = validateOverrideWeight(id, o.weight, warnings);
|
|
221
|
+
if (severity !== undefined || weight !== undefined) {
|
|
222
|
+
overrides[id] = { severity, weight };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return { disabled, overrides };
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Config overrides flow straight into scoring arithmetic β an invalid severity
|
|
229
|
+
* yields NaN totals and a negative weight yields scores outside 0β100.
|
|
230
|
+
* Reject loudly rather than corrupt the report.
|
|
231
|
+
*/
|
|
232
|
+
function validateOverrideSeverity(id, v, warnings) {
|
|
233
|
+
if (v === undefined)
|
|
234
|
+
return undefined;
|
|
235
|
+
if (SEVERITY_LADDER.includes(String(v))) {
|
|
236
|
+
return String(v);
|
|
237
|
+
}
|
|
238
|
+
warnings.push(`rules.${id}: invalid severity "${String(v)}" β override ignored`);
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
function validateOverrideWeight(id, v, warnings) {
|
|
242
|
+
if (v === undefined)
|
|
243
|
+
return undefined;
|
|
244
|
+
if (typeof v === 'number' && Number.isFinite(v) && v >= 0)
|
|
245
|
+
return v;
|
|
246
|
+
warnings.push(`rules.${id}: invalid weight "${String(v)}" (must be a finite number β₯ 0) β override ignored`);
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
function selectInitialPacks(packs, facts, include, exclude) {
|
|
250
|
+
const selection = { activePacks: [], packsLoaded: [], packsSkipped: [] };
|
|
251
|
+
selection.activePacks = packs.filter((p) => selectPack(p, facts, include, exclude, selection));
|
|
252
|
+
return selection;
|
|
253
|
+
}
|
|
254
|
+
function selectPack(pack, facts, include, exclude, selection) {
|
|
255
|
+
if (exclude.has(pack.id)) {
|
|
256
|
+
selection.packsSkipped.push(pack.id);
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
if (include.has(pack.id)) {
|
|
260
|
+
selection.packsLoaded.push(pack.id);
|
|
261
|
+
pack.provides?.forEach((f) => facts.flags.add(f));
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
if (!packApplies(pack, facts)) {
|
|
265
|
+
selection.packsSkipped.push(pack.id);
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
selection.packsLoaded.push(pack.id);
|
|
269
|
+
pack.provides?.forEach((f) => facts.flags.add(f));
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
272
|
+
function resolvePackFacts(packs, facts, include, exclude, selection) {
|
|
273
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
274
|
+
let changed = false;
|
|
275
|
+
for (const p of packs) {
|
|
276
|
+
if (selection.packsLoaded.includes(p.id) || exclude.has(p.id) || include.has(p.id))
|
|
277
|
+
continue;
|
|
278
|
+
if (!packApplies(p, facts))
|
|
279
|
+
continue;
|
|
280
|
+
selection.packsLoaded.push(p.id);
|
|
281
|
+
p.provides?.forEach((f) => facts.flags.add(f));
|
|
282
|
+
selection.activePacks.push(p);
|
|
283
|
+
changed = true;
|
|
284
|
+
}
|
|
285
|
+
if (!changed)
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function evaluatePacks(activePacks, facts, depth, include, ctx, profile) {
|
|
290
|
+
const evaluated = [];
|
|
291
|
+
for (const pack of activePacks) {
|
|
292
|
+
for (const rule of pack.rules) {
|
|
293
|
+
if (!ruleApplies(rule, facts, depth, include.has(pack.id)))
|
|
294
|
+
continue;
|
|
295
|
+
evaluated.push(scoreFinding(rule, ctx, profile));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return evaluated;
|
|
299
|
+
}
|
|
300
|
+
function scoreFinding(rule, ctx, profile) {
|
|
301
|
+
const finding = evaluateRule(rule, ctx);
|
|
302
|
+
if (finding.status === 'PASS' || finding.status === 'NOT_APPLICABLE') {
|
|
303
|
+
return { rule, finding };
|
|
304
|
+
}
|
|
305
|
+
const { severity, dampened } = dampen(rule.severity, rule.ruleClass, profile);
|
|
306
|
+
finding.severity = severity;
|
|
307
|
+
finding.dampened = dampened;
|
|
308
|
+
return { rule, finding };
|
|
309
|
+
}
|
|
310
|
+
function buildReport(opts, git, detection, facts, maturity, card, evaluated, packsLoaded, packsSkipped) {
|
|
311
|
+
return {
|
|
312
|
+
schema: 'usa-report-v1',
|
|
313
|
+
generatedAt: new Date().toISOString(),
|
|
314
|
+
usaVersion: opts.usaVersion,
|
|
315
|
+
target: {
|
|
316
|
+
path: path.resolve(opts.target),
|
|
317
|
+
name: path.basename(path.resolve(opts.target)) || opts.target,
|
|
318
|
+
commit: git.commit,
|
|
319
|
+
ref: git.ref,
|
|
320
|
+
repoUrl: git.repoUrl,
|
|
321
|
+
},
|
|
322
|
+
detection: {
|
|
323
|
+
maturity,
|
|
324
|
+
maturitySignals: detection.maturitySignals,
|
|
325
|
+
projectTypes: pick(facts, 'project'),
|
|
326
|
+
platforms: pick(facts, 'platform'),
|
|
327
|
+
languages: pick(facts, 'lang'),
|
|
328
|
+
frameworks: pick(facts, 'fw'),
|
|
329
|
+
packageManagers: pick(facts, 'pm'),
|
|
330
|
+
databases: pick(facts, 'db'),
|
|
331
|
+
flags: [...facts.flags].filter((f) => f.startsWith('has:')).sort(),
|
|
332
|
+
metrics: facts.metrics,
|
|
333
|
+
},
|
|
334
|
+
options: {
|
|
335
|
+
depth: opts.depth,
|
|
336
|
+
profile: opts.profile,
|
|
337
|
+
rulesDir: opts.rulesDir,
|
|
338
|
+
packsLoaded,
|
|
339
|
+
packsSkipped,
|
|
340
|
+
},
|
|
341
|
+
score: card,
|
|
342
|
+
findings: evaluated
|
|
343
|
+
.map((e) => e.finding)
|
|
344
|
+
.filter((f) => f.status !== 'NOT_APPLICABLE')
|
|
345
|
+
.sort(bySeverityThenSection),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function pick(facts, prefix) {
|
|
349
|
+
const out = [];
|
|
350
|
+
for (const f of facts.flags) {
|
|
351
|
+
if (f.startsWith(`${prefix}:`))
|
|
352
|
+
out.push(f.slice(prefix.length + 1));
|
|
353
|
+
}
|
|
354
|
+
return out.sort();
|
|
355
|
+
}
|
|
356
|
+
const ORDER = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3, FUTURE: 4 };
|
|
357
|
+
function bySeverityThenSection(a, b) {
|
|
358
|
+
const sa = ORDER[a.severity] ?? 9;
|
|
359
|
+
const sb = ORDER[b.severity] ?? 9;
|
|
360
|
+
if (sa !== sb)
|
|
361
|
+
return sa - sb;
|
|
362
|
+
if (a.section !== b.section)
|
|
363
|
+
return a.section.localeCompare(b.section, undefined, { numeric: true });
|
|
364
|
+
return a.ruleId.localeCompare(b.ruleId);
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/engine/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface TrailerData {
|
|
2
|
+
schema?: string;
|
|
3
|
+
generated_at?: string;
|
|
4
|
+
usa_version?: string;
|
|
5
|
+
overall?: number;
|
|
6
|
+
sections?: Record<string, {
|
|
7
|
+
score: number;
|
|
8
|
+
open: number;
|
|
9
|
+
review: number;
|
|
10
|
+
}>;
|
|
11
|
+
severity_totals?: Record<string, number>;
|
|
12
|
+
rules?: Record<string, {
|
|
13
|
+
status: string;
|
|
14
|
+
severity: string;
|
|
15
|
+
section: string;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* An audit you can't compare against the last one is just a number.
|
|
20
|
+
* `usa diff` reads the YAML trailer USA embeds in every Markdown report and
|
|
21
|
+
* reports movement: regressions, fixes, and drift.
|
|
22
|
+
*/
|
|
23
|
+
export declare function diffReports(beforeRaw: string, afterRaw: string): string;
|
|
24
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/engine/diff.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoCvE"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { parse as parseYaml } from 'yaml';
|
|
2
|
+
/**
|
|
3
|
+
* An audit you can't compare against the last one is just a number.
|
|
4
|
+
* `usa diff` reads the YAML trailer USA embeds in every Markdown report and
|
|
5
|
+
* reports movement: regressions, fixes, and drift.
|
|
6
|
+
*/
|
|
7
|
+
export function diffReports(beforeRaw, afterRaw) {
|
|
8
|
+
const before = parseYaml(beforeRaw);
|
|
9
|
+
const after = parseYaml(afterRaw);
|
|
10
|
+
if (!before || !after)
|
|
11
|
+
throw new Error('Could not parse one or both report trailers.');
|
|
12
|
+
const out = [];
|
|
13
|
+
const p = (s = '') => out.push(s);
|
|
14
|
+
const b = before.overall ?? 0;
|
|
15
|
+
const a = after.overall ?? 0;
|
|
16
|
+
const delta = Math.round((a - b) * 10) / 10;
|
|
17
|
+
renderDiffHeader(p, before, after, b, a, delta);
|
|
18
|
+
const buckets = classifyAllRules(before.rules ?? {}, after.rules ?? {});
|
|
19
|
+
const list = (title, items) => {
|
|
20
|
+
p(`## ${title} (${items.length})`);
|
|
21
|
+
p();
|
|
22
|
+
if (items.length === 0)
|
|
23
|
+
p('None. β
');
|
|
24
|
+
else
|
|
25
|
+
for (const i of items)
|
|
26
|
+
p(`- ${i}`);
|
|
27
|
+
p();
|
|
28
|
+
};
|
|
29
|
+
list('β
Fixed', buckets.fixed);
|
|
30
|
+
list('πΊ Regressed', buckets.regressed);
|
|
31
|
+
list('π‘ Changed (still open)', buckets.improved);
|
|
32
|
+
list('π Newly applicable', buckets.newRules);
|
|
33
|
+
if (buckets.goneRules.length > 0)
|
|
34
|
+
list('β No longer applicable', buckets.goneRules);
|
|
35
|
+
p('---');
|
|
36
|
+
p();
|
|
37
|
+
p(renderDiffVerdict(delta));
|
|
38
|
+
p();
|
|
39
|
+
return out.join('\n');
|
|
40
|
+
}
|
|
41
|
+
function renderDiffHeader(p, before, after, b, a, delta) {
|
|
42
|
+
p('# π USA Audit Diff');
|
|
43
|
+
p();
|
|
44
|
+
p('| | Before | After | Ξ |');
|
|
45
|
+
p('|---|---:|---:|---:|');
|
|
46
|
+
p(`| **Overall score** | ${b} | ${a} | ${sign(delta)} |`);
|
|
47
|
+
const sevKeys = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'FUTURE'];
|
|
48
|
+
for (const k of sevKeys) {
|
|
49
|
+
const bv = before.severity_totals?.[k] ?? 0;
|
|
50
|
+
const av = after.severity_totals?.[k] ?? 0;
|
|
51
|
+
p(`| ${k} | ${bv} | ${av} | ${sign(av - bv)} |`);
|
|
52
|
+
}
|
|
53
|
+
p();
|
|
54
|
+
p(`*Before: ${before.generated_at ?? 'unknown'} Β· After: ${after.generated_at ?? 'unknown'}*`);
|
|
55
|
+
p();
|
|
56
|
+
}
|
|
57
|
+
function classifyAllRules(bRules, aRules) {
|
|
58
|
+
const buckets = {
|
|
59
|
+
fixed: [],
|
|
60
|
+
regressed: [],
|
|
61
|
+
improved: [],
|
|
62
|
+
newRules: [],
|
|
63
|
+
goneRules: [],
|
|
64
|
+
};
|
|
65
|
+
const ids = [...new Set([...Object.keys(bRules), ...Object.keys(aRules)])].sort();
|
|
66
|
+
for (const id of ids) {
|
|
67
|
+
classifyRuleChange(id, bRules[id], aRules[id], buckets);
|
|
68
|
+
}
|
|
69
|
+
return buckets;
|
|
70
|
+
}
|
|
71
|
+
const PASSING = new Set(['PASS']);
|
|
72
|
+
const OPEN = new Set(['FAIL', 'WRONG', 'MISSING', 'DEPRECATED', 'EXPERIMENTAL']);
|
|
73
|
+
function classifyRuleChange(id, x, y, buckets) {
|
|
74
|
+
if (!x) {
|
|
75
|
+
buckets.newRules.push(`${id} β now applicable (${y.status})`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (!y) {
|
|
79
|
+
buckets.goneRules.push(id);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (x.status === y.status)
|
|
83
|
+
return;
|
|
84
|
+
if (classifyUnknownTransition(id, x.status, y.status, buckets))
|
|
85
|
+
return;
|
|
86
|
+
classifyOpenTransition(id, x.status, y.status, buckets);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Movements to or from the judgement queue. Previously these were dropped
|
|
90
|
+
* entirely, so resolving the queue (the tool's headline workflow) was
|
|
91
|
+
* invisible in `usa diff` β "No net movementβ¦ nothing changed" while a
|
|
92
|
+
* human did the most valuable work.
|
|
93
|
+
*/
|
|
94
|
+
function classifyUnknownTransition(id, xs, ys, buckets) {
|
|
95
|
+
if (xs !== 'UNKNOWN' && ys !== 'UNKNOWN')
|
|
96
|
+
return false;
|
|
97
|
+
if (xs === 'UNKNOWN' && ys === 'PASS') {
|
|
98
|
+
buckets.fixed.push(`${id} β UNKNOWN β PASS (resolved by review)`);
|
|
99
|
+
}
|
|
100
|
+
else if (ys === 'UNKNOWN' && !OPEN.has(xs)) {
|
|
101
|
+
buckets.regressed.push(`${id} β ${xs} β UNKNOWN (needs review)`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
buckets.improved.push(`${id} β ${xs} β ${ys}`);
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
function classifyOpenTransition(id, xs, ys, buckets) {
|
|
109
|
+
const wasOpen = OPEN.has(xs);
|
|
110
|
+
const isOpen = OPEN.has(ys);
|
|
111
|
+
if (wasOpen && PASSING.has(ys)) {
|
|
112
|
+
buckets.fixed.push(`${id} β ${xs} β PASS`);
|
|
113
|
+
}
|
|
114
|
+
else if (!wasOpen && isOpen) {
|
|
115
|
+
buckets.regressed.push(`${id} β ${xs} β ${ys}`);
|
|
116
|
+
}
|
|
117
|
+
else if (wasOpen && isOpen) {
|
|
118
|
+
buckets.improved.push(`${id} β ${xs} β ${ys}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function renderDiffVerdict(delta) {
|
|
122
|
+
if (delta > 0) {
|
|
123
|
+
return `**Net movement: +${delta} points.** Keep going β the fixed list is the progress report.`;
|
|
124
|
+
}
|
|
125
|
+
if (delta < 0) {
|
|
126
|
+
return `**Net movement: ${delta} points.** New rules became applicable, or something regressed. Start with πΊ Regressed.`;
|
|
127
|
+
}
|
|
128
|
+
return '**No net movement.** Either nothing changed, or fixes were offset by newly applicable rules.';
|
|
129
|
+
}
|
|
130
|
+
function sign(n) {
|
|
131
|
+
const v = Math.round(n * 10) / 10;
|
|
132
|
+
if (v === 0)
|
|
133
|
+
return '0';
|
|
134
|
+
return v > 0 ? `+${v}` : `${v}`;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/engine/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Depth, Facts, Finding, Predicate, Rule, RulePack, Severity } from '../types.js';
|
|
2
|
+
import { Project } from '../util/project.js';
|
|
3
|
+
export interface EvalContext {
|
|
4
|
+
project: Project;
|
|
5
|
+
facts: Facts;
|
|
6
|
+
depth: Depth;
|
|
7
|
+
allowCommands: boolean;
|
|
8
|
+
disabled: Set<string>;
|
|
9
|
+
suppressions: Map<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function evalPredicate(p: Predicate | undefined, facts: Facts): boolean;
|
|
12
|
+
export declare function ruleApplies(rule: Rule, facts: Facts, depth: Depth, includeAll?: boolean): boolean;
|
|
13
|
+
export declare function packApplies(pack: RulePack, facts: Facts): boolean;
|
|
14
|
+
export declare function evaluateRule(rule: Rule, ctx: EvalContext): Finding;
|
|
15
|
+
export declare function resolvePath(obj: unknown, dotted: string): unknown;
|
|
16
|
+
/** Effective weight of a rule: explicit override, else the severity default. */
|
|
17
|
+
export declare function ruleWeight(rule: Rule): number;
|
|
18
|
+
export declare function severityRank(s: Severity): number;
|
|
19
|
+
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/engine/evaluate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,KAAK,EACL,KAAK,EACL,OAAO,EAEP,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,EAET,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAID,wBAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAQ7E;AA+DD,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,UAAQ,GAAG,OAAO,CAS/F;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjE;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAyClE;AAuTD,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAOjE;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAEhD"}
|