audit-tools 0.30.4 → 0.30.5
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/dist/audit/contracts/schemaEnforcedEmit.d.ts +75 -0
- package/dist/audit/contracts/schemaEnforcedEmit.d.ts.map +1 -0
- package/dist/audit/contracts/schemaEnforcedEmit.js +131 -0
- package/dist/audit/contracts/schemaEnforcedEmit.js.map +1 -0
- package/dist/audit/contracts/wrapperResponse.d.ts +6 -6
- package/dist/audit/extractors/analyzers/acquisitionEngine.d.ts +140 -0
- package/dist/audit/extractors/analyzers/acquisitionEngine.d.ts.map +1 -0
- package/dist/audit/extractors/analyzers/acquisitionEngine.js +262 -0
- package/dist/audit/extractors/analyzers/acquisitionEngine.js.map +1 -0
- package/dist/audit/extractors/analyzers/registry.d.ts +2 -0
- package/dist/audit/extractors/analyzers/registry.d.ts.map +1 -1
- package/dist/audit/extractors/analyzers/registry.js +5 -0
- package/dist/audit/extractors/analyzers/registry.js.map +1 -1
- package/dist/audit/extractors/gitHistory.d.ts +46 -0
- package/dist/audit/extractors/gitHistory.d.ts.map +1 -0
- package/dist/audit/extractors/gitHistory.js +97 -0
- package/dist/audit/extractors/gitHistory.js.map +1 -0
- package/dist/audit/extractors/graph.d.ts +19 -1
- package/dist/audit/extractors/graph.d.ts.map +1 -1
- package/dist/audit/extractors/graph.js +31 -0
- package/dist/audit/extractors/graph.js.map +1 -1
- package/dist/audit/extractors/risk.d.ts +16 -0
- package/dist/audit/extractors/risk.d.ts.map +1 -1
- package/dist/audit/extractors/risk.js +28 -0
- package/dist/audit/extractors/risk.js.map +1 -1
- package/dist/audit/io/artifacts.d.ts +3 -1
- package/dist/audit/io/artifacts.d.ts.map +1 -1
- package/dist/audit/io/artifacts.js +1 -0
- package/dist/audit/io/artifacts.js.map +1 -1
- package/dist/audit/orchestrator/artifactMetadata.d.ts.map +1 -1
- package/dist/audit/orchestrator/artifactMetadata.js +24 -3
- package/dist/audit/orchestrator/artifactMetadata.js.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.d.ts +7 -0
- package/dist/audit/orchestrator/dependencyMap.d.ts.map +1 -1
- package/dist/audit/orchestrator/dependencyMap.js +5 -1
- package/dist/audit/orchestrator/dependencyMap.js.map +1 -1
- package/dist/audit/orchestrator/resultBaseline.d.ts +54 -0
- package/dist/audit/orchestrator/resultBaseline.d.ts.map +1 -1
- package/dist/audit/orchestrator/resultBaseline.js +59 -0
- package/dist/audit/orchestrator/resultBaseline.js.map +1 -1
- package/dist/audit/orchestrator/staleness.d.ts.map +1 -1
- package/dist/audit/orchestrator/staleness.js +25 -1
- package/dist/audit/orchestrator/staleness.js.map +1 -1
- package/dist/audit/quota/index.d.ts +20 -20
- package/dist/audit/types/artifactMetadata.d.ts +25 -0
- package/dist/audit/types/artifactMetadata.d.ts.map +1 -1
- package/dist/audit/types/artifactMetadata.js +10 -1
- package/dist/audit/types/artifactMetadata.js.map +1 -1
- package/dist/shared/git.d.ts +41 -0
- package/dist/shared/git.d.ts.map +1 -1
- package/dist/shared/git.js +119 -0
- package/dist/shared/git.js.map +1 -1
- package/dist/shared/index.d.ts +6 -3
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +3 -2
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/providers/providerFactory.d.ts +16 -1
- package/dist/shared/providers/providerFactory.d.ts.map +1 -1
- package/dist/shared/providers/providerFactory.js +43 -0
- package/dist/shared/providers/providerFactory.js.map +1 -1
- package/dist/shared/providers/types.d.ts +40 -0
- package/dist/shared/providers/types.d.ts.map +1 -1
- package/dist/shared/quota/capacity.d.ts +8 -8
- package/dist/shared/quota/types.d.ts +4 -4
- package/dist/shared/repair/brokeredDispatch.d.ts +147 -0
- package/dist/shared/repair/brokeredDispatch.d.ts.map +1 -0
- package/dist/shared/repair/brokeredDispatch.js +220 -0
- package/dist/shared/repair/brokeredDispatch.js.map +1 -0
- package/dist/shared/repair/index.d.ts +2 -0
- package/dist/shared/repair/index.d.ts.map +1 -1
- package/dist/shared/repair/index.js +1 -0
- package/dist/shared/repair/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { runTracked, } from "audit-tools/shared";
|
|
4
|
+
import { normalizeGenericExternalResults, normalizeGenericExternalEdges, } from "../../adapters/normalizeExternal.js";
|
|
5
|
+
/**
|
|
6
|
+
* F5 — external analyzer acquisition engine.
|
|
7
|
+
*
|
|
8
|
+
* On-demand acquisition + ephemeral execution of mature, ecosystem-native
|
|
9
|
+
* analyzers (eslint, ruff, cargo-clippy, …). Distinct from the in-tree
|
|
10
|
+
* `LanguageAnalyzer` registry (which enriches the regex floor from a resolved
|
|
11
|
+
* npm package directory): F5 *runs an external tool as a subprocess* and
|
|
12
|
+
* normalizes its native output through the EXISTING adapter seam
|
|
13
|
+
* (`normalizeExternal.ts`) into {@link ExternalAnalyzerResults}, which then
|
|
14
|
+
* re-enters the graph/risk artifacts through the shared
|
|
15
|
+
* CCU-analyzer-merge-helper-seam pair.
|
|
16
|
+
*
|
|
17
|
+
* Design invariants (all enforced here, never by host discretion):
|
|
18
|
+
* - **No baked-in language→tool / OS→runner table.** Ecosystem is detected
|
|
19
|
+
* deterministically from repo marker files; the runner (npx/pipx/cargo/bundle)
|
|
20
|
+
* is capability-probed at RUNTIME (`--version`) before any tool spawn.
|
|
21
|
+
* - **Single subprocess-SPAWN admission chokepoint** (`admitSpawn`): EVERY
|
|
22
|
+
* non-DEFAULT candidate is gated on the per-run consent token regardless of
|
|
23
|
+
* its `AnalyzerSetting` (auto|ephemeral|permanent) — even a `permanent`,
|
|
24
|
+
* pre-installed tool cannot spawn without consent (CE-005). The small
|
|
25
|
+
* value-curated DEFAULT set runs without prompting.
|
|
26
|
+
* - **Own-vs-acquire boundary.** git-history / secret-scan are OWNED by F6 and
|
|
27
|
+
* are rejected at registration — never acquired here.
|
|
28
|
+
* - **Run-safety gate written once** (`runSafetyGate`): capability-probe, pin
|
|
29
|
+
* version, read-only/sandboxed argv, degrade-to-empty.
|
|
30
|
+
* - **Degrade-to-empty + report-skipped-never-silently.** Every candidate
|
|
31
|
+
* yields exactly one {@link ExternalAnalyzerToolStatus}; a failure never
|
|
32
|
+
* throws and never silently drops the candidate.
|
|
33
|
+
*/
|
|
34
|
+
/** Tool ids OWNED by F6 (git-history mining / secret scanning). Never acquired. */
|
|
35
|
+
export const OWNED_TOOL_IDS = new Set([
|
|
36
|
+
"git-history",
|
|
37
|
+
"git-history-mining",
|
|
38
|
+
"secret-scan",
|
|
39
|
+
"secret-scanner",
|
|
40
|
+
"secrets",
|
|
41
|
+
]);
|
|
42
|
+
/** Marker-file ecosystem detection — deterministic, no language→tool table. */
|
|
43
|
+
function hasAnyMarker(root, markers) {
|
|
44
|
+
return markers.some((m) => existsSync(join(root, m)));
|
|
45
|
+
}
|
|
46
|
+
export function detectNodeEcosystem(root) {
|
|
47
|
+
return hasAnyMarker(root, ["package.json"]);
|
|
48
|
+
}
|
|
49
|
+
export function detectPythonEcosystem(root) {
|
|
50
|
+
return hasAnyMarker(root, ["pyproject.toml", "setup.py", "setup.cfg", "requirements.txt"]);
|
|
51
|
+
}
|
|
52
|
+
export function detectRustEcosystem(root) {
|
|
53
|
+
return hasAnyMarker(root, ["Cargo.toml"]);
|
|
54
|
+
}
|
|
55
|
+
export function detectRubyEcosystem(root) {
|
|
56
|
+
return hasAnyMarker(root, ["Gemfile"]);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Map a runner to the capability-probe argv (`--version`) and the argv prefix
|
|
60
|
+
* used to run a pinned tool ephemerally. No OS→runner assumption is baked in:
|
|
61
|
+
* the probe is what proves the runner exists on THIS machine.
|
|
62
|
+
*/
|
|
63
|
+
function runnerProbeArgv(runner) {
|
|
64
|
+
switch (runner) {
|
|
65
|
+
case "npx": return ["npx", "--version"];
|
|
66
|
+
case "pipx": return ["pipx", "--version"];
|
|
67
|
+
case "cargo": return ["cargo", "--version"];
|
|
68
|
+
case "bundle": return ["bundle", "--version"];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function runnerPrefix(runner, spec) {
|
|
72
|
+
switch (runner) {
|
|
73
|
+
// `-y` so the ephemeral fetch never blocks on a prompt; pinned spec.
|
|
74
|
+
case "npx": return ["npx", "-y", spec];
|
|
75
|
+
case "pipx": return ["pipx", "run", "--spec", spec];
|
|
76
|
+
case "cargo": return ["cargo", spec];
|
|
77
|
+
case "bundle": return ["bundle", "exec", spec];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Single subprocess-SPAWN admission chokepoint. Returns the reason a spawn is
|
|
82
|
+
* NOT admitted, or `undefined` when admitted. The DEFAULT set is admitted
|
|
83
|
+
* without a token; EVERY other candidate — including `permanent`/`ephemeral`
|
|
84
|
+
* pre-installed tools — requires the per-run consent token (CE-005).
|
|
85
|
+
*/
|
|
86
|
+
export function admitSpawn(candidate, setting, consentToken) {
|
|
87
|
+
if (setting === "skip")
|
|
88
|
+
return "setting=skip";
|
|
89
|
+
if (candidate.defaultRun)
|
|
90
|
+
return undefined;
|
|
91
|
+
if (consentToken && consentToken.trim().length > 0)
|
|
92
|
+
return undefined;
|
|
93
|
+
return "non-default tool requires per-run consent token";
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The run-safety gate, written once: capability-probe the runner, then (if the
|
|
97
|
+
* probe passes) the caller may spawn the pinned, read-only argv. Returns the
|
|
98
|
+
* probe outcome so a missing runner degrades to an empty result + a status.
|
|
99
|
+
*/
|
|
100
|
+
export function runSafetyGate(candidate, run, root) {
|
|
101
|
+
// Pinned version is mandatory for reproducibility — a candidate without a
|
|
102
|
+
// pinned tool spec is never executed (degrades to empty + status).
|
|
103
|
+
if (!candidate.spec || candidate.spec.trim().length === 0) {
|
|
104
|
+
return { ok: false, reason: `tool '${candidate.id}' has no pinned version spec` };
|
|
105
|
+
}
|
|
106
|
+
const probe = run(runnerProbeArgv(candidate.runner), root);
|
|
107
|
+
if (probe.error || probe.status !== 0) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
reason: `runner '${candidate.runner}' not available: ${probe.error?.message ?? `exit ${probe.status}`}`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return { ok: true };
|
|
114
|
+
}
|
|
115
|
+
function emptyResults(tool) {
|
|
116
|
+
return { tool, generated_at: new Date().toISOString(), results: [] };
|
|
117
|
+
}
|
|
118
|
+
function settingFor(analyzers, id) {
|
|
119
|
+
return analyzers?.[id] ?? "auto";
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Acquire + run ONE external analyzer candidate ephemerally, normalizing its
|
|
123
|
+
* output through the adapter seam. Never throws; always returns exactly one
|
|
124
|
+
* {@link ExternalAnalyzerToolStatus} alongside the (possibly empty) results.
|
|
125
|
+
*/
|
|
126
|
+
export function runExternalAnalyzer(candidate, root, options = {}) {
|
|
127
|
+
if (OWNED_TOOL_IDS.has(candidate.id)) {
|
|
128
|
+
// Defence in depth — registration already rejects these.
|
|
129
|
+
return {
|
|
130
|
+
results: emptyResults(candidate.id),
|
|
131
|
+
status: {
|
|
132
|
+
tool: candidate.id,
|
|
133
|
+
resolved: false,
|
|
134
|
+
status: "skipped",
|
|
135
|
+
error: "owned by F6 (git-history/secret-scan); never acquired",
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const run = options.run ?? ((argv, cwd) => runTracked(argv, { cwd }));
|
|
140
|
+
const log = options.log ?? (() => { });
|
|
141
|
+
const setting = settingFor(options.analyzers, candidate.id);
|
|
142
|
+
if (!candidate.detect(root)) {
|
|
143
|
+
return {
|
|
144
|
+
results: emptyResults(candidate.id),
|
|
145
|
+
status: { tool: candidate.id, resolved: false, status: "skipped", error: "ecosystem not detected" },
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
// Single spawn-admission chokepoint — consent gating before anything spawns.
|
|
149
|
+
const denied = admitSpawn(candidate, setting, options.consentToken);
|
|
150
|
+
if (denied) {
|
|
151
|
+
log("[f5] %s spawn not admitted: %s", candidate.id, denied);
|
|
152
|
+
return {
|
|
153
|
+
results: emptyResults(candidate.id),
|
|
154
|
+
status: { tool: candidate.id, resolved: false, status: "skipped", error: denied },
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
// Run-safety gate: capability-probe the runner before the real spawn.
|
|
158
|
+
const gate = runSafetyGate(candidate, run, root);
|
|
159
|
+
if (!gate.ok) {
|
|
160
|
+
log("[f5] %s safety gate failed: %s", candidate.id, gate.reason);
|
|
161
|
+
return {
|
|
162
|
+
results: emptyResults(candidate.id),
|
|
163
|
+
status: { tool: candidate.id, resolved: false, status: "not_resolved", error: gate.reason },
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const argv = candidate.buildArgv(runnerPrefix(candidate.runner, candidate.spec), root);
|
|
167
|
+
const command = argv.join(" ");
|
|
168
|
+
let result;
|
|
169
|
+
try {
|
|
170
|
+
result = run(argv, root);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
results: emptyResults(candidate.id),
|
|
175
|
+
status: {
|
|
176
|
+
tool: candidate.id,
|
|
177
|
+
command,
|
|
178
|
+
resolved: true,
|
|
179
|
+
status: "spawn_error",
|
|
180
|
+
error: error instanceof Error ? error.message : String(error),
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (result.error) {
|
|
185
|
+
return {
|
|
186
|
+
results: emptyResults(candidate.id),
|
|
187
|
+
status: {
|
|
188
|
+
tool: candidate.id,
|
|
189
|
+
command,
|
|
190
|
+
resolved: true,
|
|
191
|
+
status: "spawn_error",
|
|
192
|
+
exit_code: result.status,
|
|
193
|
+
error: result.error.message,
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
let items;
|
|
198
|
+
try {
|
|
199
|
+
items = candidate.parse(result.stdout);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
return {
|
|
203
|
+
results: emptyResults(candidate.id),
|
|
204
|
+
status: {
|
|
205
|
+
tool: candidate.id,
|
|
206
|
+
command,
|
|
207
|
+
resolved: true,
|
|
208
|
+
status: "parse_error",
|
|
209
|
+
exit_code: result.status,
|
|
210
|
+
error: error instanceof Error ? error.message : String(error),
|
|
211
|
+
output_snippet: result.stdout.slice(0, 200),
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const normalized = normalizeGenericExternalResults(candidate.id, items);
|
|
216
|
+
const edges = normalizeGenericExternalEdges(items);
|
|
217
|
+
if (edges.length > 0)
|
|
218
|
+
normalized.graph_edges = edges;
|
|
219
|
+
return {
|
|
220
|
+
results: normalized,
|
|
221
|
+
status: {
|
|
222
|
+
tool: candidate.id,
|
|
223
|
+
command,
|
|
224
|
+
resolved: true,
|
|
225
|
+
status: normalized.results.length > 0 ? "findings" : "success",
|
|
226
|
+
exit_code: result.status,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Register external analyzer candidates, rejecting any whose id is OWNED by F6
|
|
232
|
+
* (git-history/secret-scan). Returns the accepted candidates; the own-vs-acquire
|
|
233
|
+
* boundary is enforced HERE so an owned tool can never enter the engine.
|
|
234
|
+
*/
|
|
235
|
+
export function registerExternalAnalyzers(candidates) {
|
|
236
|
+
const accepted = [];
|
|
237
|
+
for (const candidate of candidates) {
|
|
238
|
+
if (OWNED_TOOL_IDS.has(candidate.id))
|
|
239
|
+
continue;
|
|
240
|
+
accepted.push(candidate);
|
|
241
|
+
}
|
|
242
|
+
return accepted;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Drive the whole registered candidate set through the engine for one repo,
|
|
246
|
+
* collecting one status per candidate. Owned tools are rejected at registration;
|
|
247
|
+
* each survivor passes through the spawn-admission chokepoint and run-safety gate.
|
|
248
|
+
*/
|
|
249
|
+
export function runAcquisitionEngine(candidates, root, options = {}) {
|
|
250
|
+
const registered = registerExternalAnalyzers(candidates);
|
|
251
|
+
const results = [];
|
|
252
|
+
const statuses = [];
|
|
253
|
+
for (const candidate of registered) {
|
|
254
|
+
const outcome = runExternalAnalyzer(candidate, root, options);
|
|
255
|
+
statuses.push(outcome.status);
|
|
256
|
+
if (outcome.results.results.length > 0 || outcome.results.graph_edges?.length) {
|
|
257
|
+
results.push(outcome.results);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return { results, statuses };
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=acquisitionEngine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acquisitionEngine.js","sourceRoot":"","sources":["../../../../src/audit/extractors/analyzers/acquisitionEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,8 @@ import type { AnalyzerPlanEntry, LanguageAnalyzer } from "./types.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const ANALYZER_REGISTRY: LanguageAnalyzer[];
|
|
11
11
|
export declare function getAnalyzerById(id: string): LanguageAnalyzer | undefined;
|
|
12
|
+
export { OWNED_TOOL_IDS, admitSpawn, runSafetyGate, runExternalAnalyzer, registerExternalAnalyzers, runAcquisitionEngine, detectNodeEcosystem, detectPythonEcosystem, detectRustEcosystem, detectRubyEcosystem, } from "./acquisitionEngine.js";
|
|
13
|
+
export type { EcosystemRunner, ExternalAnalyzerCandidate, AcquisitionRunner, AcquisitionEngineOptions, AcquisitionOutcome, RunAllOutcome, } from "./acquisitionEngine.js";
|
|
12
14
|
/**
|
|
13
15
|
* Deterministically resolve, without installing anything, how each registered
|
|
14
16
|
* analyzer would run for this repo. The conversation-first CLI uses this to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../src/audit/extractors/analyzers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOtE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,EAM/C,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAExE;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../../src/audit/extractors/analyzers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOtE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,EAM/C,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAExE;AAMD,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,EACb,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,eAAe,EACf,yBAAyB,EACzB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,aAAa,GACd,MAAM,wBAAwB,CAAC;AA2BhC;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,EACtD,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,iBAAiB,EAAE,CAyBrB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAEtE"}
|
|
@@ -21,6 +21,11 @@ export const ANALYZER_REGISTRY = [
|
|
|
21
21
|
export function getAnalyzerById(id) {
|
|
22
22
|
return ANALYZER_REGISTRY.find((analyzer) => analyzer.id === id);
|
|
23
23
|
}
|
|
24
|
+
// F5 external analyzer acquisition engine (on-demand ecosystem-native tools run
|
|
25
|
+
// ephemerally + normalized through the adapter seam). Re-exported here so the
|
|
26
|
+
// analyzer registry is the single entry point for both the in-tree
|
|
27
|
+
// `LanguageAnalyzer` set and the acquired external set.
|
|
28
|
+
export { OWNED_TOOL_IDS, admitSpawn, runSafetyGate, runExternalAnalyzer, registerExternalAnalyzers, runAcquisitionEngine, detectNodeEcosystem, detectPythonEcosystem, detectRustEcosystem, detectRubyEcosystem, } from "./acquisitionEngine.js";
|
|
24
29
|
function settingFor(analyzers, id) {
|
|
25
30
|
return analyzers?.[id] ?? "auto";
|
|
26
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../src/audit/extractors/analyzers/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../../src/audit/extractors/analyzers/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { GitHistory, GraphEdge, RiskRegister, RiskItem } from "audit-tools/shared";
|
|
2
|
+
import type { RepoManifest, UnitManifest } from "../types.js";
|
|
3
|
+
import type { FileDisposition } from "audit-tools/shared";
|
|
4
|
+
/**
|
|
5
|
+
* F6 — git-history mining.
|
|
6
|
+
*
|
|
7
|
+
* Deterministic extractor that turns the repository's commit log into the
|
|
8
|
+
* language-neutral `git_history.json` artifact: co-change (temporal coupling),
|
|
9
|
+
* churn (change frequency), and authorship breadth (bus-factor). All mining
|
|
10
|
+
* runs through `audit-tools/shared`'s `mineGitHistory`, which itself degrades to
|
|
11
|
+
* empty when git is unavailable / the log fails — so this extractor never
|
|
12
|
+
* throws and is safe to run on any tree (including a fresh, history-less repo).
|
|
13
|
+
*
|
|
14
|
+
* Declared upstream deps: `{repo_manifest, file_disposition}`. Both are used to
|
|
15
|
+
* scope mined paths to the audited file set (excluded / non-manifest paths are
|
|
16
|
+
* dropped) so downstream consumers see only in-scope signals.
|
|
17
|
+
*/
|
|
18
|
+
declare const GIT_CO_CHANGE_EDGE_KIND = "git-co-change";
|
|
19
|
+
/**
|
|
20
|
+
* Mine `git_history.json` for `root`, keeping only paths present (and not
|
|
21
|
+
* audit-excluded) in the manifest/disposition. Output is deterministic: the
|
|
22
|
+
* shared miner already sorts every list by a total order, and the in-scope
|
|
23
|
+
* filter preserves that order.
|
|
24
|
+
*/
|
|
25
|
+
export declare function mineGitHistoryArtifact(root: string, repoManifest: RepoManifest, disposition?: FileDisposition): GitHistory;
|
|
26
|
+
/**
|
|
27
|
+
* Project mined co-change pairs into language-neutral, undirected graph edges
|
|
28
|
+
* suitable for merging into the graph bundle via
|
|
29
|
+
* `mergeAnalyzerGraphContribution`. Confidence scales with co-change count
|
|
30
|
+
* (more shared commits → stronger coupling) up to a cap. Degrades to an empty
|
|
31
|
+
* list when there is no co-change history.
|
|
32
|
+
*/
|
|
33
|
+
export declare function gitHistoryGraphEdges(history: GitHistory): GraphEdge[];
|
|
34
|
+
/**
|
|
35
|
+
* Derive per-unit git-history risk signals (`change_hotspot`, `broad_authorship`)
|
|
36
|
+
* keyed by `unit_id`, suitable for merging into the risk register via
|
|
37
|
+
* `mergeAnalyzerRiskSignals`. A unit inherits a signal when ANY of its files is
|
|
38
|
+
* so flagged. These are informational signals (they widen the picture, they do
|
|
39
|
+
* not by themselves saturate risk). Degrades to empty when history is empty.
|
|
40
|
+
*/
|
|
41
|
+
export declare function gitHistoryRiskSignals(history: GitHistory, unitManifest: UnitManifest): Map<string, string[]>;
|
|
42
|
+
export type { GitHistory } from "audit-tools/shared";
|
|
43
|
+
export { GIT_CO_CHANGE_EDGE_KIND };
|
|
44
|
+
export type RiskRegisterForMerge = RiskRegister;
|
|
45
|
+
export type RiskItemForMerge = RiskItem;
|
|
46
|
+
//# sourceMappingURL=gitHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitHistory.d.ts","sourceRoot":"","sources":["../../../src/audit/extractors/gitHistory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI1D;;;;;;;;;;;;;GAaG;AAEH,QAAA,MAAM,uBAAuB,kBAAkB,CAAC;AAchD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,eAAe,GAC5B,UAAU,CAoBZ;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS,EAAE,CAcrE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EACnB,YAAY,EAAE,YAAY,GACzB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAuBvB;AAED,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAChD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mineGitHistory } from "audit-tools/shared";
|
|
2
|
+
import { buildDispositionMap, isAuditExcludedStatus } from "./disposition.js";
|
|
3
|
+
import { graphEdge, graphLookupKey } from "./graphPathUtils.js";
|
|
4
|
+
/**
|
|
5
|
+
* F6 — git-history mining.
|
|
6
|
+
*
|
|
7
|
+
* Deterministic extractor that turns the repository's commit log into the
|
|
8
|
+
* language-neutral `git_history.json` artifact: co-change (temporal coupling),
|
|
9
|
+
* churn (change frequency), and authorship breadth (bus-factor). All mining
|
|
10
|
+
* runs through `audit-tools/shared`'s `mineGitHistory`, which itself degrades to
|
|
11
|
+
* empty when git is unavailable / the log fails — so this extractor never
|
|
12
|
+
* throws and is safe to run on any tree (including a fresh, history-less repo).
|
|
13
|
+
*
|
|
14
|
+
* Declared upstream deps: `{repo_manifest, file_disposition}`. Both are used to
|
|
15
|
+
* scope mined paths to the audited file set (excluded / non-manifest paths are
|
|
16
|
+
* dropped) so downstream consumers see only in-scope signals.
|
|
17
|
+
*/
|
|
18
|
+
const GIT_CO_CHANGE_EDGE_KIND = "git-co-change";
|
|
19
|
+
/**
|
|
20
|
+
* Co-change is a soft, historical signal (files that *happened* to change
|
|
21
|
+
* together) — deliberately below the structural reference confidences so it
|
|
22
|
+
* never outweighs a resolved import/reference edge.
|
|
23
|
+
*/
|
|
24
|
+
const CO_CHANGE_BASE_CONFIDENCE = 0.4;
|
|
25
|
+
const CO_CHANGE_CONFIDENCE_CAP = 0.75;
|
|
26
|
+
/** Authorship floor at/above which a unit is flagged broadly-owned. */
|
|
27
|
+
const BROAD_AUTHORSHIP_FLOOR = 4;
|
|
28
|
+
/** Churn floor at/above which a unit is flagged a change hotspot. */
|
|
29
|
+
const CHURN_HOTSPOT_FLOOR = 8;
|
|
30
|
+
/**
|
|
31
|
+
* Mine `git_history.json` for `root`, keeping only paths present (and not
|
|
32
|
+
* audit-excluded) in the manifest/disposition. Output is deterministic: the
|
|
33
|
+
* shared miner already sorts every list by a total order, and the in-scope
|
|
34
|
+
* filter preserves that order.
|
|
35
|
+
*/
|
|
36
|
+
export function mineGitHistoryArtifact(root, repoManifest, disposition) {
|
|
37
|
+
const history = mineGitHistory(root);
|
|
38
|
+
const dispositionMap = buildDispositionMap(disposition);
|
|
39
|
+
const inScope = new Set();
|
|
40
|
+
for (const file of repoManifest.files) {
|
|
41
|
+
if (file.excluded)
|
|
42
|
+
continue;
|
|
43
|
+
const status = dispositionMap.get(file.path);
|
|
44
|
+
if (status && isAuditExcludedStatus(status))
|
|
45
|
+
continue;
|
|
46
|
+
inScope.add(graphLookupKey(file.path));
|
|
47
|
+
}
|
|
48
|
+
const known = (path) => inScope.has(graphLookupKey(path));
|
|
49
|
+
return {
|
|
50
|
+
co_change: history.co_change.filter((pair) => known(pair.a) && known(pair.b)),
|
|
51
|
+
churn: history.churn.filter((entry) => known(entry.path)),
|
|
52
|
+
authorship: history.authorship.filter((entry) => known(entry.path)),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Project mined co-change pairs into language-neutral, undirected graph edges
|
|
57
|
+
* suitable for merging into the graph bundle via
|
|
58
|
+
* `mergeAnalyzerGraphContribution`. Confidence scales with co-change count
|
|
59
|
+
* (more shared commits → stronger coupling) up to a cap. Degrades to an empty
|
|
60
|
+
* list when there is no co-change history.
|
|
61
|
+
*/
|
|
62
|
+
export function gitHistoryGraphEdges(history) {
|
|
63
|
+
return history.co_change.map((pair) => graphEdge({
|
|
64
|
+
from: pair.a,
|
|
65
|
+
to: pair.b,
|
|
66
|
+
kind: GIT_CO_CHANGE_EDGE_KIND,
|
|
67
|
+
direction: "undirected",
|
|
68
|
+
confidence: Math.min(CO_CHANGE_CONFIDENCE_CAP, CO_CHANGE_BASE_CONFIDENCE + 0.05 * (pair.commits - 1)),
|
|
69
|
+
reason: `Files changed together in ${pair.commits} commit(s) (temporal coupling).`,
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Derive per-unit git-history risk signals (`change_hotspot`, `broad_authorship`)
|
|
74
|
+
* keyed by `unit_id`, suitable for merging into the risk register via
|
|
75
|
+
* `mergeAnalyzerRiskSignals`. A unit inherits a signal when ANY of its files is
|
|
76
|
+
* so flagged. These are informational signals (they widen the picture, they do
|
|
77
|
+
* not by themselves saturate risk). Degrades to empty when history is empty.
|
|
78
|
+
*/
|
|
79
|
+
export function gitHistoryRiskSignals(history, unitManifest) {
|
|
80
|
+
const churnByPath = new Map(history.churn.map((e) => [e.path, e.commits]));
|
|
81
|
+
const authorsByPath = new Map(history.authorship.map((e) => [e.path, e.authors]));
|
|
82
|
+
const signalsByUnit = new Map();
|
|
83
|
+
for (const unit of unitManifest.units) {
|
|
84
|
+
const signals = [];
|
|
85
|
+
if (unit.files.some((path) => (churnByPath.get(path) ?? 0) >= CHURN_HOTSPOT_FLOOR)) {
|
|
86
|
+
signals.push("change_hotspot");
|
|
87
|
+
}
|
|
88
|
+
if (unit.files.some((path) => (authorsByPath.get(path) ?? 0) >= BROAD_AUTHORSHIP_FLOOR)) {
|
|
89
|
+
signals.push("broad_authorship");
|
|
90
|
+
}
|
|
91
|
+
if (signals.length > 0)
|
|
92
|
+
signalsByUnit.set(unit.unit_id, signals);
|
|
93
|
+
}
|
|
94
|
+
return signalsByUnit;
|
|
95
|
+
}
|
|
96
|
+
export { GIT_CO_CHANGE_EDGE_KIND };
|
|
97
|
+
//# sourceMappingURL=gitHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitHistory.js","sourceRoot":"","sources":["../../../src/audit/extractors/gitHistory.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RepoManifest } from "../types.js";
|
|
2
|
-
import type { FileDisposition, GraphBundle } from "audit-tools/shared";
|
|
2
|
+
import type { FileDisposition, GraphBundle, GraphEdge } from "audit-tools/shared";
|
|
3
3
|
import type { ExternalAnalyzerResults } from "../types/externalAnalyzer.js";
|
|
4
4
|
export interface BuildGraphBundleOptions {
|
|
5
5
|
fileContents?: Record<string, string>;
|
|
@@ -7,5 +7,23 @@ export interface BuildGraphBundleOptions {
|
|
|
7
7
|
}
|
|
8
8
|
export declare function buildPathLookup(repoManifest: RepoManifest, dispositionMap: Map<string, FileDisposition["files"][number]["status"]>): Map<string, string>;
|
|
9
9
|
export declare function buildGraphBundleFromFs(repoManifest: RepoManifest, root: string, disposition?: FileDisposition, options?: Pick<BuildGraphBundleOptions, "externalAnalyzerResults">): Promise<GraphBundle>;
|
|
10
|
+
/**
|
|
11
|
+
* CCU-analyzer-merge-helper-seam (graph half).
|
|
12
|
+
*
|
|
13
|
+
* Append an analyzer's contributed edges into a graph bundle's edge categories,
|
|
14
|
+
* returning a NEW bundle (the input is never mutated). This is the single,
|
|
15
|
+
* pre-shipped seam through which any post-build analyzer contribution —
|
|
16
|
+
* git-history co-change (F6), and any later F5+ analyzer — re-enters the graph,
|
|
17
|
+
* so contributions can never drift in how they merge.
|
|
18
|
+
*
|
|
19
|
+
* Merged into `graphs.references` by default (the open-ended cross-file edge
|
|
20
|
+
* category) under one `category` key, then deduped + sorted by the same
|
|
21
|
+
* `uniqueSortedEdges` the build uses, so the result is deterministic and an edge
|
|
22
|
+
* already present (same from/to/kind) is idempotent. Degrades to the original
|
|
23
|
+
* bundle (structurally cloned) when `edges` is empty / not an array.
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeAnalyzerGraphContribution(bundle: GraphBundle, edges: GraphEdge[] | undefined, options?: {
|
|
26
|
+
category?: string;
|
|
27
|
+
}): GraphBundle;
|
|
10
28
|
export declare function buildGraphBundle(repoManifest: RepoManifest, disposition?: FileDisposition, options?: BuildGraphBundleOptions): GraphBundle;
|
|
11
29
|
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/audit/extractors/graph.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,eAAe,EACf,WAAW,
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/audit/extractors/graph.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,SAAS,EAGV,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAgD5E,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;CACnD;AAmED,wBAAgB,eAAe,CAC7B,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,GACtE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASrB;AAmTD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,eAAe,EAC7B,OAAO,GAAE,IAAI,CAAC,uBAAuB,EAAE,yBAAyB,CAAM,GACrE,OAAO,CAAC,WAAW,CAAC,CA4CtB;AAsND;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAC9B,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClC,WAAW,CAeb;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,YAAY,EAC1B,WAAW,CAAC,EAAE,eAAe,EAC7B,OAAO,GAAE,uBAA4B,GACpC,WAAW,CA8Db"}
|
|
@@ -474,6 +474,37 @@ function accumulateCrossFileEdges(acc, pathLookup, options) {
|
|
|
474
474
|
acc.references.push(...extractPytestConftestLinks(pathLookup));
|
|
475
475
|
acc.references.push(...extractBoundedSuiteEdges(pathLookup, options.fileContents ?? {}, acc.references));
|
|
476
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* CCU-analyzer-merge-helper-seam (graph half).
|
|
479
|
+
*
|
|
480
|
+
* Append an analyzer's contributed edges into a graph bundle's edge categories,
|
|
481
|
+
* returning a NEW bundle (the input is never mutated). This is the single,
|
|
482
|
+
* pre-shipped seam through which any post-build analyzer contribution —
|
|
483
|
+
* git-history co-change (F6), and any later F5+ analyzer — re-enters the graph,
|
|
484
|
+
* so contributions can never drift in how they merge.
|
|
485
|
+
*
|
|
486
|
+
* Merged into `graphs.references` by default (the open-ended cross-file edge
|
|
487
|
+
* category) under one `category` key, then deduped + sorted by the same
|
|
488
|
+
* `uniqueSortedEdges` the build uses, so the result is deterministic and an edge
|
|
489
|
+
* already present (same from/to/kind) is idempotent. Degrades to the original
|
|
490
|
+
* bundle (structurally cloned) when `edges` is empty / not an array.
|
|
491
|
+
*/
|
|
492
|
+
export function mergeAnalyzerGraphContribution(bundle, edges, options = {}) {
|
|
493
|
+
const category = options.category ?? "references";
|
|
494
|
+
const existing = bundle.graphs;
|
|
495
|
+
const existingEdges = Array.isArray(existing[category])
|
|
496
|
+
? existing[category]
|
|
497
|
+
: [];
|
|
498
|
+
const contributed = Array.isArray(edges) ? edges : [];
|
|
499
|
+
const merged = uniqueSortedEdges([...existingEdges, ...contributed]);
|
|
500
|
+
return {
|
|
501
|
+
...bundle,
|
|
502
|
+
graphs: {
|
|
503
|
+
...bundle.graphs,
|
|
504
|
+
[category]: merged,
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
}
|
|
477
508
|
export function buildGraphBundle(repoManifest, disposition, options = {}) {
|
|
478
509
|
const acc = {
|
|
479
510
|
imports: [],
|