@xenos1996/usa 2.15.0 → 2.16.1

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.
@@ -0,0 +1,152 @@
1
+ /** Help texts and scaffold templates (pure data — no imports). Generated docs embed the help. */
2
+ export const MODELS_HELP_TEXT = `
3
+ usa models — list models a provider advertises
4
+
5
+ usa models --provider ID
6
+
7
+ Prints one model id per line (live listing, static default on fallback).
8
+ Use it to check a model id exists before a session spends calls on a 404.
9
+ `.trim();
10
+ export const LIVE_HELP_TEXT = `
11
+ usa live — conversational audit session
12
+
13
+ usa live [path] [--provider ID] [--model M] [--transcript FILE] [--triage-limit N] [--dry-run]
14
+
15
+ Walks foundation → audit → triage → report with you. The deterministic
16
+ engine verifies; the model only proposes. Without a provider the session
17
+ runs deterministically (model turns are skipped loudly, never faked).
18
+
19
+ --provider <id> LLM provider preset (default $USA_PROVIDER, else deterministic-only)
20
+ --model <m> Model id (default preset default or $USA_MODEL)
21
+ --transcript <file> Write the session transcript to this file
22
+ --triage-limit <n> Max findings to walk in triage (default 15, ceiling 50)
23
+ --dry-run Print the transcript path that would be written and exit
24
+ `.trim();
25
+ export const HELP = `
26
+ usa — Universal Software Auditor
27
+
28
+ usa audit [path] Audit a project and write a Markdown report
29
+ usa detect [path] Print the auto-detected facts and maturity
30
+ usa rules [--section S2] List all loaded rule packs and rules
31
+ usa explain <RULE-ID> Show everything about one rule
32
+ usa diff <before> <after> Compare two previously generated reports
33
+ usa verify-report <AUDIT.md> Verify a report's detached signature sidecar
34
+ usa init [path] Scaffold .usa.yaml + a GitHub Actions workflow
35
+ usa bootstrap [path] Propose rule packs for stacks USA cannot audit yet
36
+ usa learn <report.md> Generate suggested rules from audit findings
37
+ usa evolve [path] Run the audit → gap → candidate → release loop
38
+ usa standards Report catalogue coverage and automatability
39
+ usa categories Report future-domain category coverage
40
+ usa foundation init [path] Capture project intent into .usa/foundation.yaml
41
+ usa foundation show [path] Print the effective intent and asserted facts
42
+ usa live [path] Conversational audit session (deterministic without a provider)
43
+ usa models --provider ID List models the provider advertises
44
+
45
+ evolve options
46
+ --dry-run Print what would be written and exit (no cycle, no store writes)
47
+ --store <dir> Persist audit runs/results (content-addressed store)
48
+ --candidate <file> A candidate capability pack (YAML) to benchmark and release
49
+ --propose Auto-propose a candidate from the gaps (bootstrap catalog)
50
+ --all-gaps Evaluate every proposable candidate (one per open gap)
51
+ --learn <report.md> Propose a candidate from a report's open findings (usa learn)
52
+ --min-severity <s> Min severity for --learn (default MEDIUM)
53
+ --bench-dir <dir> Directory of benchmark case *.json files
54
+ --rules-dir <dir> Rule pack directory (default bundled rules/)
55
+
56
+ learn options
57
+ --dry-run Print the output path that would be written and exit
58
+ --out <file> Output YAML file (default learn-suggestions.yaml)
59
+ --min-severity <s> Minimum severity to consider (CRITICAL|HIGH|MEDIUM|LOW|FUTURE, default MEDIUM)
60
+
61
+ standards options
62
+ --format <fmt> md | json (default md)
63
+ --rules-dir <dir> Rule pack directory (default bundled rules/)
64
+
65
+ categories options
66
+ --format <fmt> md | json (default md)
67
+ --rules-dir <dir> Rule pack directory (default bundled rules/)
68
+
69
+ foundation options
70
+ --dir <path> Project directory (default .; a positional path works too)
71
+ --non-interactive Write the defaults file without prompting (init only)
72
+ --dry-run Print the file that would be written and exit (init only)
73
+
74
+ live options
75
+ --dry-run Print the transcript path that would be written and exit
76
+ --provider <id> LLM provider preset (default $USA_PROVIDER, else deterministic-only)
77
+ --model <m> Model id (default preset default or $USA_MODEL)
78
+ --transcript <file> Write the session transcript to this file
79
+ --triage-limit <n> Max findings to walk in triage (default 15, ceiling 50)
80
+
81
+ models options
82
+ --provider <id> LLM provider preset (or $USA_PROVIDER)
83
+
84
+ audit options
85
+ --dry-run Print the report path that would be written and exit
86
+ --out <file> Report path (default AUDIT.md)
87
+ --format <fmt> md | json | sarif | narrative | html (default: inferred from --out)
88
+ --depth <level> quick | standard | deep (default standard)
89
+ --profile <stage> auto | prototype | mvp | beta | production | legacy
90
+ --rules-dir <dir> Rule pack directory (default bundled rules/)
91
+ --config <file> Explicit .usa.yaml location
92
+ --include <packs> Force these packs on (comma separated)
93
+ --exclude <packs> Force these packs off
94
+ --fact <ns:value> Assert a fact detection missed, e.g. --fact has:database
95
+ --allow-commands Run \`command:\` checks (shells out; off by default)
96
+ --fail-on <sev> Exit 1 on findings >= sev: critical|high|medium|low|none
97
+ --baseline <file> New-code gate: only fail on findings new or regressed
98
+ vs this previous report (default threshold high;
99
+ explicit --fail-on overrides it)
100
+ --quiet Only errors
101
+ --max-files <n> Index at most n files (overrides config; default 60000)
102
+ --max-bytes <n> Skip files larger than n bytes (overrides config; default 2 MiB)
103
+
104
+ bootstrap options
105
+ --dry-run Print the path that would be written and exit (with --out)
106
+ --out <file|dir> Write pack files instead of printing (default: print)
107
+
108
+ init options
109
+ --dry-run Print the files that would be scaffolded and exit
110
+
111
+ verify-report options
112
+ --bundle <file> Signature sidecar (required, e.g. AUDIT.md.sig.json)
113
+ --key <file> PEM public key the bundle is verified against
114
+ --cosign-binary <bin> Override the cosign binary (default cosign)
115
+ --quiet Only errors
116
+
117
+ examples
118
+ usa audit . --depth deep
119
+ usa bootstrap ~/code/legacy-php-app --out /tmp/packs
120
+ usa audit ../api --profile production --fail-on high
121
+ usa audit . --baseline reports/2026-08.md --fail-on high
122
+ usa audit . --out reports/audit-$(date +%F).md
123
+ usa learn AUDIT.md --out swift-suggestions.yaml
124
+ usa verify-report AUDIT.md --bundle AUDIT.md.sig.json --key cosign.pub
125
+ `.trim();
126
+ export const WORKFLOW_TEMPLATE = `# USA — Universal Software Auditor
127
+ # Runs on every PR and pushes a Markdown summary you can read in the Actions UI.
128
+ name: USA Audit
129
+
130
+ on:
131
+ pull_request:
132
+ push:
133
+ branches: [master]
134
+ workflow_dispatch:
135
+ inputs:
136
+ depth:
137
+ description: Audit depth
138
+ required: false
139
+ default: standard
140
+ type: choice
141
+ options: [quick, standard, deep]
142
+
143
+ permissions:
144
+ contents: read
145
+ `;
146
+ // ---- main entry point ----
147
+ // Run only when this file is the entry point. Comparing `import.meta.url` to
148
+ // `file://${process.argv[1]}` breaks under npm's bin symlinks: argv[1] is the
149
+ // `.bin/usa` symlink while import.meta.url is the real dist/cli.js path, so
150
+ // the guard never matches and the CLI exits silently. Resolve argv[1] to its
151
+ // real path first (and guard the fs call so a non-file argv never throws).
152
+ //# sourceMappingURL=cli-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,iGAAiG;AAEjG,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;CAO/B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;CAc7B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGnB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;CAmBhC,CAAC;AAEF,6BAA6B;AAC7B,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,2EAA2E"}
@@ -0,0 +1,13 @@
1
+ import { type Args } from './cli-args.js';
2
+ /** Read-only catalogue queries: detect, rules, explain, standards, categories. */
3
+ export declare function cmdDetect(args: Args): number;
4
+ export declare function cmdRules(args: Args): number;
5
+ export declare function cmdExplain(args: Args): number;
6
+ export declare function cmdStandards(args: Args): number;
7
+ /**
8
+ * Category coverage is derived, never scored (ADR-0030 taxonomy rule): the
9
+ * table answers "which future domains already have rules" without touching
10
+ * scoring, gates, or confidence.
11
+ */
12
+ export declare function cmdCategories(args: Args): number;
13
+ //# sourceMappingURL=cli-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-query.d.ts","sourceRoot":"","sources":["../src/cli-query.ts"],"names":[],"mappings":"AAWA,OAAO,EAAgC,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAExE,kFAAkF;AAGlF,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAwB5C;AAgBD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAsB3C;AAID,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAiB7C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAmB/C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAmBhD"}
@@ -0,0 +1,166 @@
1
+ import path from 'node:path';
2
+ import { detect } from './detect/index.js';
3
+ import { loadDetectorFile } from './detect/index.js';
4
+ import { Project } from './util/project.js';
5
+ import { loadRulePacks } from './engine/loader.js';
6
+ import { catalogueCoverage, catalogueOf, loadCatalogues } from './engine/catalogues.js';
7
+ import { categoryCoverage, loadCategories } from './engine/categories.js';
8
+ import { loadConfig } from './config.js';
9
+ import { ruleAutomatability } from './engine/automatability.js';
10
+ import { DEFAULT_RULES_DIR, list, str } from './cli-args.js';
11
+ /** Read-only catalogue queries: detect, rules, explain, standards, categories. */
12
+ /* ----------------------------------------------------------------- detect -- */
13
+ export function cmdDetect(args) {
14
+ const target = args._[1] ?? '.';
15
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
16
+ const config = loadConfig(target, str(args, 'config'));
17
+ const project = new Project(target, config.ignore ?? []);
18
+ const git = project.gitInfo();
19
+ const detection = detect(project, loadDetectorFile(rulesDir), git, [
20
+ ...list(args, 'fact'),
21
+ ...(config.facts ?? []),
22
+ ]);
23
+ const grouped = groupFlagsByNamespace(detection.facts.flags);
24
+ console.log(`# Detection: ${path.resolve(target)}`);
25
+ console.log();
26
+ console.log(`maturity: ${detection.maturity}`);
27
+ for (const [ns, values] of [...grouped.entries()].sort()) {
28
+ console.log(`${ns}: ${[...new Set(values)].sort().join(', ')}`);
29
+ }
30
+ console.log();
31
+ console.log('metrics:');
32
+ for (const [k, v] of Object.entries(detection.facts.metrics))
33
+ console.log(` ${k}: ${v}`);
34
+ console.log();
35
+ console.log('maturity signals:');
36
+ for (const s of detection.maturitySignals)
37
+ console.log(` ${s}`);
38
+ return 0;
39
+ }
40
+ function groupFlagsByNamespace(flags) {
41
+ const grouped = new Map();
42
+ for (const f of flags) {
43
+ const [ns, value] = f.split(':');
44
+ const key = value === undefined ? 'other' : ns;
45
+ const list2 = grouped.get(key) ?? [];
46
+ list2.push(value === undefined ? f : value);
47
+ grouped.set(key, list2);
48
+ }
49
+ return grouped;
50
+ }
51
+ /* ------------------------------------------------------------------ rules -- */
52
+ export function cmdRules(args) {
53
+ if (args['format'] !== undefined) {
54
+ console.error('warning: rules has no --format; ignoring');
55
+ }
56
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
57
+ const { packs } = loadRulePacks(rulesDir);
58
+ const filter = str(args, 'section');
59
+ let total = 0;
60
+ for (const pack of packs) {
61
+ const rules = filter ? pack.rules.filter((r) => r.section === filter) : pack.rules;
62
+ if (filter && rules.length === 0)
63
+ continue;
64
+ console.log(`\n## ${pack.id} — ${pack.title} (${rules.length} rules)`);
65
+ if (pack.description)
66
+ console.log(` ${pack.description}`);
67
+ for (const r of rules) {
68
+ total++;
69
+ console.log(` ${r.id.padEnd(10)} ${r.severity.padEnd(8)} ${r.ruleClass.padEnd(16)} ${r.title}`);
70
+ }
71
+ }
72
+ console.log(`\n${total} rule(s) across ${packs.length} pack(s).`);
73
+ return 0;
74
+ }
75
+ /* ---------------------------------------------------------------- explain -- */
76
+ export function cmdExplain(args) {
77
+ const id = args._[1];
78
+ if (!id) {
79
+ console.error('Usage: usa explain <RULE-ID>');
80
+ return 2;
81
+ }
82
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
83
+ const { packs } = loadRulePacks(rulesDir);
84
+ const { catalogues } = loadCatalogues(rulesDir);
85
+ for (const pack of packs) {
86
+ const rule = pack.rules.find((r) => r.id.toLowerCase() === id.toLowerCase());
87
+ if (!rule)
88
+ continue;
89
+ printRuleDetail(pack.id, rule, catalogues);
90
+ return 0;
91
+ }
92
+ console.error(`Rule not found: ${id}`);
93
+ return 1;
94
+ }
95
+ export function cmdStandards(args) {
96
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
97
+ const { packs } = loadRulePacks(rulesDir);
98
+ const { catalogues } = loadCatalogues(rulesDir);
99
+ const rows = catalogueCoverage(packs, catalogues);
100
+ const fmt = (str(args, 'format') ?? 'md').toLowerCase();
101
+ if (fmt === 'json') {
102
+ console.log(JSON.stringify(rows, null, 2));
103
+ return 0;
104
+ }
105
+ // Markdown table: catalogue → rules → how many the engine can fully decide.
106
+ console.log('| Catalogue | Rules | Fully automated | Assisted | Manual |');
107
+ console.log('| --------- | ----- | --------------- | -------- | ------ |');
108
+ for (const row of rows) {
109
+ console.log(`| ${row.name} (\`${row.catalogue}\`) | ${row.rules} | ${row.automatable.full} | ${row.automatable.assist} | ${row.automatable.manual} |`);
110
+ }
111
+ return 0;
112
+ }
113
+ /**
114
+ * Category coverage is derived, never scored (ADR-0030 taxonomy rule): the
115
+ * table answers "which future domains already have rules" without touching
116
+ * scoring, gates, or confidence.
117
+ */
118
+ export function cmdCategories(args) {
119
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
120
+ const { packs } = loadRulePacks(rulesDir);
121
+ const { categories, warnings } = loadCategories(rulesDir);
122
+ for (const w of warnings)
123
+ console.error(`warning: ${w}`);
124
+ const rows = categoryCoverage(packs, categories);
125
+ const fmt = (str(args, 'format') ?? 'md').toLowerCase();
126
+ if (fmt === 'json') {
127
+ console.log(JSON.stringify(rows, null, 2));
128
+ return 0;
129
+ }
130
+ console.log('| Category | Rules | Sections |');
131
+ console.log('| -------- | ----- | -------- |');
132
+ for (const row of rows) {
133
+ console.log(`| ${row.name} (\`${row.id}\`) | ${row.ruleCount} | ${row.sections.join(', ') || '—'} |`);
134
+ }
135
+ return 0;
136
+ }
137
+ function printRuleDetail(packId, rule, catalogues) {
138
+ console.log(`# ${rule.id} — ${rule.title}`);
139
+ console.log();
140
+ console.log(`pack : ${packId}`);
141
+ console.log(`section : ${rule.section} ${rule.sectionTitle ?? ''}`);
142
+ console.log(`severity : ${rule.severity} (when violated)`);
143
+ console.log(`class : ${rule.ruleClass}`);
144
+ console.log(`weight : ${rule.weight ?? 'default'}`);
145
+ console.log(`depths : ${rule.depths?.join(', ') ?? 'all'}`);
146
+ console.log(`automatable: ${ruleAutomatability(rule)}`);
147
+ const catalogue = catalogueOf(rule, catalogues);
148
+ if (catalogue)
149
+ console.log(`catalogue : ${catalogue}`);
150
+ console.log(`check : ${JSON.stringify(rule.check)}`);
151
+ printRuleOptional(rule);
152
+ }
153
+ function printRuleOptional(rule) {
154
+ if (rule.appliesWhen)
155
+ console.log(`applies : ${JSON.stringify(rule.appliesWhen)}`);
156
+ if (rule.why)
157
+ console.log(`\nwhy:\n ${rule.why}`);
158
+ if (rule.evidence)
159
+ console.log(`\nevidence:\n ${rule.evidence}`);
160
+ if (rule.remediation)
161
+ console.log(`\nfix:\n ${rule.remediation}`);
162
+ if (rule.references?.length)
163
+ console.log(`\nreferences:\n ${rule.references.join('\n ')}`);
164
+ }
165
+ /* ------------------------------------------------------------------- diff -- */
166
+ //# sourceMappingURL=cli-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-query.js","sourceRoot":"","sources":["../src/cli-query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type Args } from './cli-args.js';
2
+ /** Report operations: diffing two reports, verifying a signed report. */
3
+ export declare function cmdDiff(args: Args): number;
4
+ export declare function cmdVerifyReport(args: Args): number;
5
+ //# sourceMappingURL=cli-reports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-reports.d.ts","sourceRoot":"","sources":["../src/cli-reports.ts"],"names":[],"mappings":"AAQA,OAAO,EAA2B,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAGnE,yEAAyE;AAGzE,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB1C;AAcD,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA+BlD"}
@@ -0,0 +1,111 @@
1
+ import fs from 'node:fs';
2
+ import { diffReports } from './engine/diff.js';
3
+ import { parseTrailer } from './report/markdown.js';
4
+ import { parseDetachedSignature, verifyDetachedSignature, } from './report/signature.js';
5
+ import { bool, dryRunWrites, str } from './cli-args.js';
6
+ import { writeTextFile } from './util/files.js';
7
+ /** Report operations: diffing two reports, verifying a signed report. */
8
+ /* ------------------------------------------------------------------- diff -- */
9
+ export function cmdDiff(args) {
10
+ const beforePath = args._[1];
11
+ const afterPath = args._[2];
12
+ if (!beforePath || !afterPath) {
13
+ console.error('Usage: usa diff <before.md> <after.md> [--out DIFF.md] [--dry-run]');
14
+ return 2;
15
+ }
16
+ // CLI-003: preview before reading or comparing anything.
17
+ const diffOut = str(args, 'out');
18
+ if (!dryRunWrites(args, diffOut ? [diffOut] : []))
19
+ return 0;
20
+ const readTrailer = (file) => {
21
+ const text = fs.readFileSync(file, 'utf8');
22
+ return parseTrailer(text) ?? text; // tolerate a raw YAML trailer file
23
+ };
24
+ try {
25
+ const md = diffReports(readTrailer(beforePath), readTrailer(afterPath));
26
+ if (diffOut)
27
+ writeTextFile(diffOut, md);
28
+ console.log(md);
29
+ return 0;
30
+ }
31
+ catch (err) {
32
+ console.error(err.message);
33
+ return 2;
34
+ }
35
+ }
36
+ /* -------------------------------------------------------- verify-report -- */
37
+ /** Reads a text input, or reports it loudly and returns null (exit 2). */
38
+ function readTextInput(file, label) {
39
+ try {
40
+ return fs.readFileSync(file, 'utf8');
41
+ }
42
+ catch {
43
+ console.error(`${label} not found or unreadable: ${file}`);
44
+ return null;
45
+ }
46
+ }
47
+ export function cmdVerifyReport(args) {
48
+ const reportPath = args._[1];
49
+ const bundlePath = str(args, 'bundle');
50
+ if (!reportPath || !bundlePath) {
51
+ console.error('Usage: usa verify-report <AUDIT.md> --bundle <sidecar.sig.json> [--key <pubkey>] [--cosign-binary <path>] [--quiet]');
52
+ return 2;
53
+ }
54
+ const markdown = readTextInput(reportPath, 'Report file');
55
+ if (markdown === null)
56
+ return 2;
57
+ const sidecarRaw = readTextInput(bundlePath, 'Signature sidecar');
58
+ if (sidecarRaw === null)
59
+ return 2;
60
+ const trailerYaml = parseTrailer(markdown);
61
+ if (!trailerYaml || !trailerYaml.trim()) {
62
+ console.error(`Report has no machine-readable trailer: ${reportPath}`);
63
+ return 2;
64
+ }
65
+ let signature;
66
+ try {
67
+ signature = parseDetachedSignature(sidecarRaw);
68
+ }
69
+ catch (err) {
70
+ console.error(`Signature sidecar is malformed (${bundlePath}): ${err.message}`);
71
+ return 2;
72
+ }
73
+ // Payload bytes are exactly canonicalReportBytes(report) for the report
74
+ // that rendered this trailer: the trailer projection plus '\n'. The CLI
75
+ // only ever sees rendered bytes, so it reconstructs them from the parsed
76
+ // trailer rather than re-deriving a report object.
77
+ const payload = Buffer.from(`${trailerYaml}\n`, 'utf8');
78
+ return runSignatureVerify(args, reportPath, payload, signature);
79
+ }
80
+ /**
81
+ * Runs the cosign verification and maps the outcome onto the gate
82
+ * convention: 0 verified, 1 mismatch/failed, 2 environment refusal (an
83
+ * absent cosign binary throws — a loud error, never a fake pass).
84
+ */
85
+ function runSignatureVerify(args, reportPath, payload, signature) {
86
+ const quiet = bool(args, 'quiet');
87
+ const cosignBinary = str(args, 'cosign-binary');
88
+ let result;
89
+ try {
90
+ result = verifyDetachedSignature(payload, signature, {
91
+ publicKeyPath: str(args, 'key') ?? '',
92
+ ...(cosignBinary === undefined ? {} : { cosignBinary }),
93
+ });
94
+ }
95
+ catch (err) {
96
+ console.error(err.message);
97
+ return 2;
98
+ }
99
+ if (result.ok) {
100
+ if (!quiet)
101
+ console.log(`Signature verified: ${reportPath}`);
102
+ return 0;
103
+ }
104
+ // Gate convention: the mismatch detail goes to stderr, suppressed by
105
+ // --quiet; the exit code alone carries the verdict then.
106
+ if (!quiet)
107
+ console.error(`Signature verification failed for ${reportPath}: ${result.detail}`);
108
+ return 1;
109
+ }
110
+ /* -------------------------------------------------------------- bootstrap -- */
111
+ //# sourceMappingURL=cli-reports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-reports.js","sourceRoot":"","sources":["../src/cli-reports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type Args } from './cli-args.js';
2
+ /** Scaffolding and generation: bootstrap packs, init, learn suggestions. */
3
+ export declare function cmdBootstrap(args: Args): number;
4
+ export declare function cmdInit(args: Args): number;
5
+ export declare function cmdLearn(args: Args): number;
6
+ //# sourceMappingURL=cli-scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-scaffold.d.ts","sourceRoot":"","sources":["../src/cli-scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,EAA8C,KAAK,IAAI,EAAE,MAAM,eAAe,CAAC;AAItF,4EAA4E;AAG5E,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB/C;AAyBD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA6B1C;AAID,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAsC3C"}
@@ -0,0 +1,129 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { detect } from './detect/index.js';
4
+ import { loadDetectorFile } from './detect/index.js';
5
+ import { Project } from './util/project.js';
6
+ import { bootstrapPacks, writeBootstrapPacks } from './bootstrap/index.js';
7
+ import { EXAMPLE_CONFIG, loadConfig } from './config.js';
8
+ import { learnFromReport, renderSuggestions } from './learn/index.js';
9
+ import { DEFAULT_RULES_DIR, dryRunWrites, list, str } from './cli-args.js';
10
+ import { WORKFLOW_TEMPLATE } from './cli-help.js';
11
+ import { writeTextFile } from './util/files.js';
12
+ /** Scaffolding and generation: bootstrap packs, init, learn suggestions. */
13
+ /* -------------------------------------------------------------- bootstrap -- */
14
+ export function cmdBootstrap(args) {
15
+ const target = args._[1] ?? '.';
16
+ const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
17
+ const config = loadConfig(target, str(args, 'config'));
18
+ const project = new Project(target, config.ignore ?? []);
19
+ const git = project.gitInfo();
20
+ const out = str(args, 'out');
21
+ // CLI-003: preview before detection runs.
22
+ if (out && !dryRunWrites(args, [out]))
23
+ return 0;
24
+ const detection = detect(project, loadDetectorFile(rulesDir), git, [
25
+ ...list(args, 'fact'),
26
+ ...(config.facts ?? []),
27
+ ]);
28
+ const outcome = bootstrapPacks(detection.facts);
29
+ if (outcome.packs.length === 0) {
30
+ console.log('No uncovered stacks: every detected language already has a pack.');
31
+ return 0;
32
+ }
33
+ if (!out) {
34
+ printBootstrap(outcome);
35
+ return 0;
36
+ }
37
+ return writeBootstrapResult(outcome, out);
38
+ }
39
+ /** Write packs to --out with a clean error (exit 2), never a stack trace. */
40
+ function writeBootstrapResult(outcome, out) {
41
+ try {
42
+ writeBootstrapPacks(outcome, out);
43
+ }
44
+ catch (err) {
45
+ console.error(err.message);
46
+ return 2;
47
+ }
48
+ console.log(`wrote ${outcome.packs.length} pack(s) to ${out}`);
49
+ for (const note of outcome.notes)
50
+ console.log(`- ${note}`);
51
+ return 0;
52
+ }
53
+ function printBootstrap(outcome) {
54
+ for (const pack of outcome.packs) {
55
+ console.log(`--- ${pack.filename} ---`);
56
+ console.log(pack.yaml);
57
+ }
58
+ for (const note of outcome.notes)
59
+ console.log(`- ${note}`);
60
+ }
61
+ /* ------------------------------------------------------------------- init -- */
62
+ export function cmdInit(args) {
63
+ const target = args._[1] ?? '.';
64
+ const configPath = path.join(target, '.usa.yaml');
65
+ const workflowDir = path.join(target, '.github', 'workflows');
66
+ const workflowPath = path.join(workflowDir, 'usa.yml');
67
+ // CLI-003: preview the scaffold before creating anything.
68
+ if (!dryRunWrites(args, [configPath, workflowPath].filter((p) => !fs.existsSync(p))))
69
+ return 0;
70
+ fs.mkdirSync(target, { recursive: true });
71
+ if (fs.existsSync(configPath)) {
72
+ console.error(`${configPath} already exists — leaving it alone.`);
73
+ }
74
+ else {
75
+ fs.writeFileSync(configPath, EXAMPLE_CONFIG, 'utf8');
76
+ console.log(`created ${configPath}`);
77
+ }
78
+ if (fs.existsSync(workflowPath)) {
79
+ console.error(`${workflowPath} already exists — leaving it alone.`);
80
+ }
81
+ else {
82
+ fs.mkdirSync(workflowDir, { recursive: true });
83
+ fs.writeFileSync(workflowPath, WORKFLOW_TEMPLATE, 'utf8');
84
+ console.log(`created ${workflowPath}`);
85
+ }
86
+ console.log('\nNext: run `npx usa audit .` or `usa audit . --depth standard`.');
87
+ return 0;
88
+ }
89
+ /* ------------------------------------------------------------------ learn -- */
90
+ export function cmdLearn(args) {
91
+ const reportPath = args._[1];
92
+ if (!reportPath) {
93
+ console.error('Usage: usa learn <report.md> [--out <file>] [--min-severity MEDIUM] [--dry-run]');
94
+ return 2;
95
+ }
96
+ if (!fs.existsSync(reportPath)) {
97
+ console.error(`Report file not found: ${reportPath}`);
98
+ return 2;
99
+ }
100
+ const outFile = str(args, 'out', 'learn-suggestions.yaml') ?? 'learn-suggestions.yaml';
101
+ const minSeverity = (str(args, 'min-severity', 'MEDIUM') ?? 'MEDIUM').toUpperCase();
102
+ const allowed = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'FUTURE'];
103
+ if (!allowed.includes(minSeverity)) {
104
+ console.error(`--min-severity must be one of: ${allowed.join(', ')}`);
105
+ return 2;
106
+ }
107
+ // CLI-003: preview before the report is mined.
108
+ if (!dryRunWrites(args, [outFile]))
109
+ return 0;
110
+ const options = { reportPath, out: outFile, minSeverity };
111
+ try {
112
+ const suggestions = learnFromReport(options);
113
+ if (suggestions.length === 0) {
114
+ console.log(`No actionable suggestions found in ${reportPath}.`);
115
+ return 0;
116
+ }
117
+ const yaml = renderSuggestions(suggestions);
118
+ writeTextFile(outFile, yaml);
119
+ console.log(`Wrote ${suggestions.length} suggestion(s) to ${outFile}`);
120
+ console.log(' Review the rules, test them, then register in rules/index.yaml.');
121
+ return 0;
122
+ }
123
+ catch (err) {
124
+ console.error(err.message);
125
+ return 2;
126
+ }
127
+ }
128
+ /* ----------------------------------------------------------------- evolve -- */
129
+ //# sourceMappingURL=cli-scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-scaffold.js","sourceRoot":"","sources":["../src/cli-scaffold.ts"],"names":[],"mappings":"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"}