@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
package/dist/cli.js
ADDED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { runAudit } from './engine/audit.js';
|
|
6
|
+
import { loadRulePacks } from './engine/loader.js';
|
|
7
|
+
import { loadDetectorFile } from './detect/index.js';
|
|
8
|
+
import { Project } from './util/project.js';
|
|
9
|
+
import { detect } from './detect/index.js';
|
|
10
|
+
import { renderMarkdown, parseTrailer } from './report/markdown.js';
|
|
11
|
+
import { diffReports } from './engine/diff.js';
|
|
12
|
+
import { EXAMPLE_CONFIG, loadConfig } from './config.js';
|
|
13
|
+
import { evaluateGate } from './engine/gate.js';
|
|
14
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const DEFAULT_RULES_DIR = path.resolve(HERE, '..', 'rules');
|
|
16
|
+
const VERSION = readVersion();
|
|
17
|
+
const SEVERITY_ORDER = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'FUTURE'];
|
|
18
|
+
const DEPTHS = ['quick', 'standard', 'deep'];
|
|
19
|
+
const MATURITIES = ['prototype', 'mvp', 'beta', 'production', 'legacy'];
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const args = { _: [] };
|
|
22
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23
|
+
const tok = argv[i];
|
|
24
|
+
if (!tok.startsWith('--')) {
|
|
25
|
+
args._.push(tok);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const body = tok.slice(2);
|
|
29
|
+
if (body.includes('=')) {
|
|
30
|
+
const [k, ...rest] = body.split('=');
|
|
31
|
+
args[k] = rest.join('=');
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const next = argv[i + 1];
|
|
35
|
+
if (next === undefined || next.startsWith('--')) {
|
|
36
|
+
args[body] = true;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
args[body] = next;
|
|
40
|
+
i++;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return args;
|
|
44
|
+
}
|
|
45
|
+
function str(args, key, fallback) {
|
|
46
|
+
const v = args[key];
|
|
47
|
+
return typeof v === 'string' ? v : fallback;
|
|
48
|
+
}
|
|
49
|
+
function bool(args, key) {
|
|
50
|
+
return args[key] === true || args[key] === 'true';
|
|
51
|
+
}
|
|
52
|
+
function list(args, key) {
|
|
53
|
+
const v = args[key];
|
|
54
|
+
if (Array.isArray(v))
|
|
55
|
+
return v;
|
|
56
|
+
if (typeof v === 'string')
|
|
57
|
+
return v
|
|
58
|
+
.split(',')
|
|
59
|
+
.map((s) => s.trim())
|
|
60
|
+
.filter(Boolean);
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
/* -------------------------------------------------------------------- main -- */
|
|
64
|
+
const COMMANDS = {
|
|
65
|
+
audit: cmdAudit,
|
|
66
|
+
detect: cmdDetect,
|
|
67
|
+
rules: cmdRules,
|
|
68
|
+
explain: cmdExplain,
|
|
69
|
+
diff: cmdDiff,
|
|
70
|
+
init: cmdInit,
|
|
71
|
+
};
|
|
72
|
+
export function main(argv) {
|
|
73
|
+
const args = parseArgs(argv);
|
|
74
|
+
// GNU-style flags never reach `_` (the parser files them under flags), so
|
|
75
|
+
// check them before the command dispatch: without this, `usat --help`
|
|
76
|
+
// falls through to the default `audit` command and audits the tree
|
|
77
|
+
// instead of printing help. The `version`/`--version` cases below exist
|
|
78
|
+
// for the positional forms (`usat version`); the flags are handled here.
|
|
79
|
+
if (bool(args, 'help')) {
|
|
80
|
+
console.log(HELP);
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
if (bool(args, 'version')) {
|
|
84
|
+
console.log(`usat ${VERSION}`);
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
const cmd = (args._[0] ?? 'audit');
|
|
88
|
+
const run = COMMANDS[cmd];
|
|
89
|
+
if (run)
|
|
90
|
+
return run(args);
|
|
91
|
+
switch (cmd) {
|
|
92
|
+
case 'version':
|
|
93
|
+
case '--version':
|
|
94
|
+
console.log(`usat ${VERSION}`);
|
|
95
|
+
return 0;
|
|
96
|
+
case 'help':
|
|
97
|
+
case '--help':
|
|
98
|
+
case '-h':
|
|
99
|
+
console.log(HELP);
|
|
100
|
+
return 0;
|
|
101
|
+
default:
|
|
102
|
+
console.error(`Unknown command: ${cmd}\n`);
|
|
103
|
+
console.error(HELP);
|
|
104
|
+
return 2;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function readAuditOptions(args) {
|
|
108
|
+
return {
|
|
109
|
+
target: args._[1] ?? '.',
|
|
110
|
+
rulesDir: path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR),
|
|
111
|
+
depth: str(args, 'depth', 'standard') ?? 'standard',
|
|
112
|
+
profileArg: str(args, 'profile', 'auto') ?? 'auto',
|
|
113
|
+
out: str(args, 'out', 'AUDIT.md') ?? 'AUDIT.md',
|
|
114
|
+
failOn: (str(args, 'fail-on', 'none') ?? 'none').toLowerCase(),
|
|
115
|
+
quiet: bool(args, 'quiet'),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function validateAuditOptions(o) {
|
|
119
|
+
if (!DEPTHS.includes(o.depth))
|
|
120
|
+
return `--depth must be one of ${DEPTHS.join('|')}`;
|
|
121
|
+
if (o.profileArg !== 'auto' && !MATURITIES.includes(o.profileArg)) {
|
|
122
|
+
return `--profile must be auto or one of ${MATURITIES.join('|')}`;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
function cmdAudit(args) {
|
|
127
|
+
const o = readAuditOptions(args);
|
|
128
|
+
const invalid = validateAuditOptions(o);
|
|
129
|
+
if (invalid) {
|
|
130
|
+
console.error(invalid);
|
|
131
|
+
return 2;
|
|
132
|
+
}
|
|
133
|
+
if (!fs.existsSync(o.target)) {
|
|
134
|
+
console.error(`Target path does not exist: ${o.target}`);
|
|
135
|
+
return 2;
|
|
136
|
+
}
|
|
137
|
+
let config;
|
|
138
|
+
try {
|
|
139
|
+
config = loadConfig(o.target, str(args, 'config'));
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
console.error(err.message);
|
|
143
|
+
return 2;
|
|
144
|
+
}
|
|
145
|
+
if (config.facts)
|
|
146
|
+
config.facts = [...config.facts, ...list(args, 'fact')];
|
|
147
|
+
const { report, warnings, profile } = runAudit({
|
|
148
|
+
target: o.target,
|
|
149
|
+
rulesDir: o.rulesDir,
|
|
150
|
+
depth: o.depth,
|
|
151
|
+
profile: o.profileArg,
|
|
152
|
+
config,
|
|
153
|
+
allowCommands: bool(args, 'allow-commands'),
|
|
154
|
+
usatVersion: VERSION,
|
|
155
|
+
includePacks: list(args, 'include'),
|
|
156
|
+
excludePacks: list(args, 'exclude'),
|
|
157
|
+
});
|
|
158
|
+
for (const w of warnings)
|
|
159
|
+
console.error(`warning: ${w}`);
|
|
160
|
+
const markdown = renderMarkdown(report, profile);
|
|
161
|
+
fs.writeFileSync(o.out, markdown, 'utf8');
|
|
162
|
+
if (!o.quiet) {
|
|
163
|
+
console.log(summaryLine(report));
|
|
164
|
+
console.log(` report → ${o.out}`);
|
|
165
|
+
}
|
|
166
|
+
return evaluateGate(report, o.failOn, o.quiet);
|
|
167
|
+
}
|
|
168
|
+
function summaryLine(report) {
|
|
169
|
+
const s = report.score.severityCounts;
|
|
170
|
+
const parts = SEVERITY_ORDER.filter((k) => s[k] > 0)
|
|
171
|
+
.map((k) => `${k.toLowerCase()} ${s[k]}`)
|
|
172
|
+
.join(' · ');
|
|
173
|
+
return (`usat ${report.score.overall}/100 (${report.detection.maturity}) — ` +
|
|
174
|
+
`${report.score.counts.PASS} passed, ` +
|
|
175
|
+
(parts ? `open: ${parts}` : 'no open findings') +
|
|
176
|
+
`, ${report.score.counts.UNKNOWN} to review` +
|
|
177
|
+
` (${report.score.automationCoverage}% verified automatically)`);
|
|
178
|
+
}
|
|
179
|
+
/* ----------------------------------------------------------------- detect -- */
|
|
180
|
+
function cmdDetect(args) {
|
|
181
|
+
const target = args._[1] ?? '.';
|
|
182
|
+
const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
|
|
183
|
+
const config = loadConfig(target, str(args, 'config'));
|
|
184
|
+
// Honour `ignore:`, so detecting a repo whose own files (rule packs, docs)
|
|
185
|
+
// mention every technology under the sun does not light up the whole map.
|
|
186
|
+
const project = new Project(target, config.ignore ?? []);
|
|
187
|
+
const git = project.gitInfo();
|
|
188
|
+
const detection = detect(project, loadDetectorFile(rulesDir), git, [
|
|
189
|
+
...list(args, 'fact'),
|
|
190
|
+
...(config.facts ?? []),
|
|
191
|
+
]);
|
|
192
|
+
const grouped = groupFlagsByNamespace(detection.facts.flags);
|
|
193
|
+
console.log(`# Detection: ${path.resolve(target)}`);
|
|
194
|
+
console.log();
|
|
195
|
+
console.log(`maturity: ${detection.maturity}`);
|
|
196
|
+
for (const [ns, values] of [...grouped.entries()].sort()) {
|
|
197
|
+
console.log(`${ns}: ${[...new Set(values)].sort().join(', ')}`);
|
|
198
|
+
}
|
|
199
|
+
console.log();
|
|
200
|
+
console.log('metrics:');
|
|
201
|
+
for (const [k, v] of Object.entries(detection.facts.metrics))
|
|
202
|
+
console.log(` ${k}: ${v}`);
|
|
203
|
+
console.log();
|
|
204
|
+
console.log('maturity signals:');
|
|
205
|
+
for (const s of detection.maturitySignals)
|
|
206
|
+
console.log(` ${s}`);
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
function groupFlagsByNamespace(flags) {
|
|
210
|
+
const grouped = new Map();
|
|
211
|
+
for (const f of flags) {
|
|
212
|
+
const [ns, value] = f.split(':');
|
|
213
|
+
const key = value === undefined ? 'other' : ns;
|
|
214
|
+
const list2 = grouped.get(key) ?? [];
|
|
215
|
+
list2.push(value === undefined ? f : value);
|
|
216
|
+
grouped.set(key, list2);
|
|
217
|
+
}
|
|
218
|
+
return grouped;
|
|
219
|
+
}
|
|
220
|
+
/* ------------------------------------------------------------------ rules -- */
|
|
221
|
+
function cmdRules(args) {
|
|
222
|
+
const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
|
|
223
|
+
const { packs } = loadRulePacks(rulesDir);
|
|
224
|
+
const filter = str(args, 'section');
|
|
225
|
+
let total = 0;
|
|
226
|
+
for (const pack of packs) {
|
|
227
|
+
const rules = filter ? pack.rules.filter((r) => r.section === filter) : pack.rules;
|
|
228
|
+
if (filter && rules.length === 0)
|
|
229
|
+
continue;
|
|
230
|
+
console.log(`\n## ${pack.id} — ${pack.title} (${rules.length} rules)`);
|
|
231
|
+
if (pack.description)
|
|
232
|
+
console.log(` ${pack.description}`);
|
|
233
|
+
for (const r of rules) {
|
|
234
|
+
total++;
|
|
235
|
+
console.log(` ${r.id.padEnd(10)} ${r.severity.padEnd(8)} ${r.ruleClass.padEnd(16)} ${r.title}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
console.log(`\n${total} rule(s) across ${packs.length} pack(s).`);
|
|
239
|
+
return 0;
|
|
240
|
+
}
|
|
241
|
+
/* ---------------------------------------------------------------- explain -- */
|
|
242
|
+
function cmdExplain(args) {
|
|
243
|
+
const id = args._[1];
|
|
244
|
+
if (!id) {
|
|
245
|
+
console.error('Usage: usat explain <RULE-ID>');
|
|
246
|
+
return 2;
|
|
247
|
+
}
|
|
248
|
+
const rulesDir = path.resolve(str(args, 'rules-dir', DEFAULT_RULES_DIR) ?? DEFAULT_RULES_DIR);
|
|
249
|
+
const { packs } = loadRulePacks(rulesDir);
|
|
250
|
+
for (const pack of packs) {
|
|
251
|
+
const rule = pack.rules.find((r) => r.id.toLowerCase() === id.toLowerCase());
|
|
252
|
+
if (!rule)
|
|
253
|
+
continue;
|
|
254
|
+
printRuleDetail(pack.id, rule);
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
console.error(`Rule not found: ${id}`);
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
function printRuleDetail(packId, rule) {
|
|
261
|
+
console.log(`# ${rule.id} — ${rule.title}`);
|
|
262
|
+
console.log();
|
|
263
|
+
console.log(`pack : ${packId}`);
|
|
264
|
+
console.log(`section : ${rule.section} ${rule.sectionTitle ?? ''}`);
|
|
265
|
+
console.log(`severity : ${rule.severity} (when violated)`);
|
|
266
|
+
console.log(`class : ${rule.ruleClass}`);
|
|
267
|
+
console.log(`weight : ${rule.weight ?? 'default'}`);
|
|
268
|
+
console.log(`depths : ${rule.depths?.join(', ') ?? 'all'}`);
|
|
269
|
+
console.log(`check : ${JSON.stringify(rule.check)}`);
|
|
270
|
+
printRuleOptional(rule);
|
|
271
|
+
}
|
|
272
|
+
function printRuleOptional(rule) {
|
|
273
|
+
if (rule.appliesWhen)
|
|
274
|
+
console.log(`applies : ${JSON.stringify(rule.appliesWhen)}`);
|
|
275
|
+
if (rule.why)
|
|
276
|
+
console.log(`\nwhy:\n ${rule.why}`);
|
|
277
|
+
if (rule.evidence)
|
|
278
|
+
console.log(`\nevidence:\n ${rule.evidence}`);
|
|
279
|
+
if (rule.remediation)
|
|
280
|
+
console.log(`\nfix:\n ${rule.remediation}`);
|
|
281
|
+
if (rule.references?.length)
|
|
282
|
+
console.log(`\nreferences:\n ${rule.references.join('\n ')}`);
|
|
283
|
+
}
|
|
284
|
+
/* ------------------------------------------------------------------- diff -- */
|
|
285
|
+
function cmdDiff(args) {
|
|
286
|
+
const beforePath = args._[1];
|
|
287
|
+
const afterPath = args._[2];
|
|
288
|
+
if (!beforePath || !afterPath) {
|
|
289
|
+
console.error('Usage: usat diff <before.md> <after.md> [--out DIFF.md]');
|
|
290
|
+
return 2;
|
|
291
|
+
}
|
|
292
|
+
const readTrailer = (file) => {
|
|
293
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
294
|
+
return parseTrailer(text) ?? text; // tolerate a raw YAML trailer file
|
|
295
|
+
};
|
|
296
|
+
try {
|
|
297
|
+
const md = diffReports(readTrailer(beforePath), readTrailer(afterPath));
|
|
298
|
+
const out = str(args, 'out');
|
|
299
|
+
if (out)
|
|
300
|
+
fs.writeFileSync(out, md, 'utf8');
|
|
301
|
+
console.log(md);
|
|
302
|
+
return 0;
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
console.error(err.message);
|
|
306
|
+
return 2;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/* ------------------------------------------------------------------- init -- */
|
|
310
|
+
function cmdInit(args) {
|
|
311
|
+
const target = args._[1] ?? '.';
|
|
312
|
+
fs.mkdirSync(target, { recursive: true });
|
|
313
|
+
const configPath = path.join(target, '.usat.yaml');
|
|
314
|
+
if (fs.existsSync(configPath)) {
|
|
315
|
+
console.error(`${configPath} already exists — leaving it alone.`);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
fs.writeFileSync(configPath, EXAMPLE_CONFIG, 'utf8');
|
|
319
|
+
console.log(`created ${configPath}`);
|
|
320
|
+
}
|
|
321
|
+
const workflowDir = path.join(target, '.github', 'workflows');
|
|
322
|
+
const workflowPath = path.join(workflowDir, 'usat.yml');
|
|
323
|
+
if (fs.existsSync(workflowPath)) {
|
|
324
|
+
console.error(`${workflowPath} already exists — leaving it alone.`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
fs.mkdirSync(workflowDir, { recursive: true });
|
|
328
|
+
fs.writeFileSync(workflowPath, WORKFLOW_TEMPLATE, 'utf8');
|
|
329
|
+
console.log(`created ${workflowPath}`);
|
|
330
|
+
}
|
|
331
|
+
console.log('\nNext: run `npx usat audit .` or `usat audit . --depth standard`.');
|
|
332
|
+
return 0;
|
|
333
|
+
}
|
|
334
|
+
/* ------------------------------------------------------------------ utils -- */
|
|
335
|
+
function readVersion() {
|
|
336
|
+
const candidates = [
|
|
337
|
+
path.resolve(HERE, '..', 'package.json'),
|
|
338
|
+
path.resolve(HERE, '..', '..', 'package.json'),
|
|
339
|
+
];
|
|
340
|
+
for (const c of candidates) {
|
|
341
|
+
try {
|
|
342
|
+
const pkg = JSON.parse(fs.readFileSync(c, 'utf8'));
|
|
343
|
+
if (pkg.version)
|
|
344
|
+
return pkg.version;
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
/* fall through */
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return '0.0.0';
|
|
351
|
+
}
|
|
352
|
+
const HELP = `
|
|
353
|
+
usat — Universal Software Audit Template
|
|
354
|
+
|
|
355
|
+
usat audit [path] Audit a project and write a Markdown report
|
|
356
|
+
usat detect [path] Print the auto-detected facts and maturity
|
|
357
|
+
usat rules [--section S2] List all loaded rule packs and rules
|
|
358
|
+
usat explain <RULE-ID> Show everything about one rule
|
|
359
|
+
usat diff <before> <after> Compare two previously generated reports
|
|
360
|
+
usat init [path] Scaffold .usat.yaml + a GitHub Actions workflow
|
|
361
|
+
|
|
362
|
+
audit options
|
|
363
|
+
--out <file> Report path (default AUDIT.md)
|
|
364
|
+
--depth <level> quick | standard | deep (default standard)
|
|
365
|
+
--profile <stage> auto | prototype | mvp | beta | production | legacy
|
|
366
|
+
--rules-dir <dir> Rule pack directory (default bundled rules/)
|
|
367
|
+
--config <file> Explicit .usat.yaml location
|
|
368
|
+
--include <packs> Force these packs on (comma separated)
|
|
369
|
+
--exclude <packs> Force these packs off
|
|
370
|
+
--fact <ns:value> Assert a fact detection missed, e.g. --fact has:database
|
|
371
|
+
--allow-commands Run \`command:\` checks (shells out; off by default)
|
|
372
|
+
--fail-on <sev> Exit 1 on findings >= sev: critical|high|medium|low|none
|
|
373
|
+
--quiet Only errors
|
|
374
|
+
|
|
375
|
+
examples
|
|
376
|
+
usat audit . --depth deep
|
|
377
|
+
usat audit ../api --profile production --fail-on high
|
|
378
|
+
usat audit . --out reports/audit-$(date +%F).md
|
|
379
|
+
`.trim();
|
|
380
|
+
const WORKFLOW_TEMPLATE = `# USAT — Universal Software Audit Template
|
|
381
|
+
# Runs on every PR and pushes a Markdown summary you can read in the Actions UI.
|
|
382
|
+
name: USAT Audit
|
|
383
|
+
|
|
384
|
+
on:
|
|
385
|
+
pull_request:
|
|
386
|
+
push:
|
|
387
|
+
branches: [master]
|
|
388
|
+
workflow_dispatch:
|
|
389
|
+
inputs:
|
|
390
|
+
depth:
|
|
391
|
+
description: Audit depth
|
|
392
|
+
required: false
|
|
393
|
+
default: standard
|
|
394
|
+
type: choice
|
|
395
|
+
options: [quick, standard, deep]
|
|
396
|
+
|
|
397
|
+
permissions:
|
|
398
|
+
contents: read
|
|
399
|
+
pull-requests: write
|
|
400
|
+
|
|
401
|
+
jobs:
|
|
402
|
+
audit:
|
|
403
|
+
runs-on: ubuntu-latest
|
|
404
|
+
steps:
|
|
405
|
+
- uses: actions/checkout@v4
|
|
406
|
+
|
|
407
|
+
- uses: actions/setup-node@v4
|
|
408
|
+
with:
|
|
409
|
+
node-version: '20'
|
|
410
|
+
|
|
411
|
+
- name: Run USAT
|
|
412
|
+
id: usat
|
|
413
|
+
run: |
|
|
414
|
+
npx --yes usat@latest audit . \\
|
|
415
|
+
--depth \${{ inputs.depth || 'standard' }} \\
|
|
416
|
+
--out AUDIT.md
|
|
417
|
+
|
|
418
|
+
- name: Publish to job summary
|
|
419
|
+
if: always()
|
|
420
|
+
run: cat AUDIT.md >> "$GITHUB_STEP_SUMMARY"
|
|
421
|
+
|
|
422
|
+
- name: Upload report
|
|
423
|
+
if: always()
|
|
424
|
+
uses: actions/upload-artifact@v4
|
|
425
|
+
with:
|
|
426
|
+
name: usat-audit
|
|
427
|
+
path: AUDIT.md
|
|
428
|
+
|
|
429
|
+
# Uncomment to gate the merge on HIGH findings.
|
|
430
|
+
# - name: Quality gate
|
|
431
|
+
# run: npx --yes usat@latest audit . --fail-on high
|
|
432
|
+
`.trimStart();
|
|
433
|
+
/* Entrypoint. */
|
|
434
|
+
const isDirectRun = process.argv[1] ? /usat|cli\.(ts|js)$/.test(process.argv[1]) : false;
|
|
435
|
+
if (isDirectRun) {
|
|
436
|
+
process.exitCode = main(process.argv.slice(2));
|
|
437
|
+
}
|
|
438
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UsatConfig } from './types.js';
|
|
2
|
+
export declare const CONFIG_FILE = ".usat.yaml";
|
|
3
|
+
export declare const EMPTY_CONFIG: UsatConfig;
|
|
4
|
+
/** Loads `<target>/.usat.yaml` when present. Missing config is not an error. */
|
|
5
|
+
export declare function loadConfig(target: string, explicit?: string): UsatConfig;
|
|
6
|
+
export declare const EXAMPLE_CONFIG = "# USAT project configuration \u2014 commit this file.\n# Docs: docs/configuration.md\nversion: 1\n\n# Force a lifecycle stage instead of auto-detecting (prototype|mvp|beta|production|legacy).\n# maturity: production\n\n# Rule packs to force on or off, regardless of auto-detection.\n# include: [stacks/node-typescript]\n# exclude: [stacks/solidity]\n\n# Per-rule overrides. Every entry should carry a reason \u2014 this file is audited too.\nrules:\n # DOC-003:\n # severity: LOW\n # reason: \"Docs live in Notion, not the repo (decision: ADR-014)\"\n # SEC-042:\n # disabled: true\n # reason: \"Not applicable \u2014 no user-facing auth in this worker\"\n\n# Accepted risk. USAT still lists these, but excludes them from the score.\nsuppressions:\n # - rule: PERF-005\n # reason: \"Known N+1 in the admin panel; 40 rows max. Revisit Q4.\"\n # until: \"2026-12-31\"\n\n# Extra globs to exclude from indexing (on top of .gitignore + USAT defaults).\nignore: []\n\n# Assert facts detection could not infer. Useful for non-standard layouts.\nfacts: []\n";
|
|
7
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,eAAO,MAAM,WAAW,eAAe,CAAC;AAExC,eAAO,MAAM,YAAY,EAAE,UAA2B,CAAC;AAEvD,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CA4BxE;AAED,eAAO,MAAM,cAAc,ojCA+B1B,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { parse as parseYaml } from 'yaml';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { asMap, maps, str, strList } from './util/yaml.js';
|
|
5
|
+
export const CONFIG_FILE = '.usat.yaml';
|
|
6
|
+
export const EMPTY_CONFIG = { version: 1 };
|
|
7
|
+
/** Loads `<target>/.usat.yaml` when present. Missing config is not an error. */
|
|
8
|
+
export function loadConfig(target, explicit) {
|
|
9
|
+
const file = explicit ?? path.join(target, CONFIG_FILE);
|
|
10
|
+
if (!fs.existsSync(file))
|
|
11
|
+
return { ...EMPTY_CONFIG };
|
|
12
|
+
try {
|
|
13
|
+
const raw = parseYaml(fs.readFileSync(file, 'utf8'));
|
|
14
|
+
if (raw === null || typeof raw === 'undefined')
|
|
15
|
+
return { ...EMPTY_CONFIG };
|
|
16
|
+
if (typeof raw !== 'object' || Array.isArray(raw)) {
|
|
17
|
+
throw new Error(`${file}: expected a YAML mapping at the top level`);
|
|
18
|
+
}
|
|
19
|
+
const doc = raw;
|
|
20
|
+
return {
|
|
21
|
+
version: 1,
|
|
22
|
+
maturity: str(doc.maturity),
|
|
23
|
+
include: strList(doc.include),
|
|
24
|
+
exclude: strList(doc.exclude),
|
|
25
|
+
rules: asMap(doc.rules),
|
|
26
|
+
suppressions: maps(doc.suppressions).map((s) => ({
|
|
27
|
+
rule: String(s.rule ?? ''),
|
|
28
|
+
reason: str(s.reason) ?? 'no reason recorded',
|
|
29
|
+
until: str(s.until),
|
|
30
|
+
})),
|
|
31
|
+
ignore: strList(doc.ignore),
|
|
32
|
+
facts: strList(doc.facts),
|
|
33
|
+
sections: strList(doc.sections),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw new Error(`Could not parse ${file}: ${err.message}`, { cause: err });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export const EXAMPLE_CONFIG = `# USAT project configuration — commit this file.
|
|
41
|
+
# Docs: docs/configuration.md
|
|
42
|
+
version: 1
|
|
43
|
+
|
|
44
|
+
# Force a lifecycle stage instead of auto-detecting (prototype|mvp|beta|production|legacy).
|
|
45
|
+
# maturity: production
|
|
46
|
+
|
|
47
|
+
# Rule packs to force on or off, regardless of auto-detection.
|
|
48
|
+
# include: [stacks/node-typescript]
|
|
49
|
+
# exclude: [stacks/solidity]
|
|
50
|
+
|
|
51
|
+
# Per-rule overrides. Every entry should carry a reason — this file is audited too.
|
|
52
|
+
rules:
|
|
53
|
+
# DOC-003:
|
|
54
|
+
# severity: LOW
|
|
55
|
+
# reason: "Docs live in Notion, not the repo (decision: ADR-014)"
|
|
56
|
+
# SEC-042:
|
|
57
|
+
# disabled: true
|
|
58
|
+
# reason: "Not applicable — no user-facing auth in this worker"
|
|
59
|
+
|
|
60
|
+
# Accepted risk. USAT still lists these, but excludes them from the score.
|
|
61
|
+
suppressions:
|
|
62
|
+
# - rule: PERF-005
|
|
63
|
+
# reason: "Known N+1 in the admin panel; 40 rows max. Revisit Q4."
|
|
64
|
+
# until: "2026-12-31"
|
|
65
|
+
|
|
66
|
+
# Extra globs to exclude from indexing (on top of .gitignore + USAT defaults).
|
|
67
|
+
ignore: []
|
|
68
|
+
|
|
69
|
+
# Assert facts detection could not infer. Useful for non-standard layouts.
|
|
70
|
+
facts: []
|
|
71
|
+
`;
|
|
72
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAe,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAEvD,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,QAAiB;IAC1D,MAAM,IAAI,GAAG,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACxD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACrD,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,WAAW;YAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;QAC3E,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,4CAA4C,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,GAAG,GAA4B,GAA8B,CAAC;QACpE,OAAO;YACL,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,QAAQ,CAA2B;YACrD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC7B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAC7B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAwB;YAC9C,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/C,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC1B,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,oBAAoB;gBAC7C,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;aACpB,CAAC,CAAC;YACH,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAC3B,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YACzB,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;SAChC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+B7B,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Facts, Maturity } from '../types.js';
|
|
2
|
+
import { Project } from '../util/project.js';
|
|
3
|
+
interface DetectorMatch {
|
|
4
|
+
any_file?: string[];
|
|
5
|
+
file_exists?: string[];
|
|
6
|
+
dir_exists?: string[];
|
|
7
|
+
content?: {
|
|
8
|
+
include: string[];
|
|
9
|
+
pattern: string;
|
|
10
|
+
};
|
|
11
|
+
manifest?: {
|
|
12
|
+
file: string;
|
|
13
|
+
key: string;
|
|
14
|
+
contains?: string;
|
|
15
|
+
};
|
|
16
|
+
metric?: {
|
|
17
|
+
name: string;
|
|
18
|
+
min?: number;
|
|
19
|
+
max?: number;
|
|
20
|
+
};
|
|
21
|
+
any_of?: DetectorMatch[];
|
|
22
|
+
all_of?: DetectorMatch[];
|
|
23
|
+
}
|
|
24
|
+
interface Detector {
|
|
25
|
+
fact: string;
|
|
26
|
+
category: string;
|
|
27
|
+
title: string;
|
|
28
|
+
match?: DetectorMatch;
|
|
29
|
+
implies?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface DetectionResult {
|
|
32
|
+
facts: Facts;
|
|
33
|
+
detectorsFired: {
|
|
34
|
+
fact: string;
|
|
35
|
+
title: string;
|
|
36
|
+
category: string;
|
|
37
|
+
}[];
|
|
38
|
+
maturity: Maturity;
|
|
39
|
+
maturitySignals: string[];
|
|
40
|
+
}
|
|
41
|
+
/** Load the detector registry. */
|
|
42
|
+
export declare function loadDetectors(file: string): Detector[];
|
|
43
|
+
/** Run every detector against the project and derive the fact set. */
|
|
44
|
+
export declare function detect(project: Project, detectors: Detector[], git: ReturnType<Project['gitInfo']>, extraFacts?: string[]): DetectionResult;
|
|
45
|
+
/**
|
|
46
|
+
* Lifecycle classification. Deliberately conservative: a project is only
|
|
47
|
+
* called "production" when it has release tags, CI, tests and recent activity.
|
|
48
|
+
* The result drives severity dampening so a prototype is not graded like a
|
|
49
|
+
* bank.
|
|
50
|
+
*/
|
|
51
|
+
export declare function classifyMaturity(flags: Set<string>, metrics: Record<string, number>, project?: Project): {
|
|
52
|
+
maturity: Maturity;
|
|
53
|
+
signals: string[];
|
|
54
|
+
};
|
|
55
|
+
export declare function factsByPrefix(facts: Facts, prefix: string): string[];
|
|
56
|
+
export declare function loadDetectorFile(rulesDir: string): Detector[];
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAI7C,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAmCD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpE,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,kCAAkC;AAClC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAStD;AAED,sEAAsE;AACtE,wBAAgB,MAAM,CACpB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,QAAQ,EAAE,EACrB,GAAG,EAAE,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EACnC,UAAU,GAAE,MAAM,EAAO,GACxB,eAAe,CAgCjB;AAwND;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,EAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAuC3C;AA+BD,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAMpE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE,CAE7D"}
|