bilt-toolkit 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 +0 -0
- package/README.md +168 -0
- package/bin/bilt.js +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +161 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor.d.ts +13 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +194 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/fix.d.ts +12 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +273 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +101 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/scan.d.ts +17 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +267 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/undo.d.ts +12 -0
- package/dist/commands/undo.d.ts.map +1 -0
- package/dist/commands/undo.js +90 -0
- package/dist/commands/undo.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +68 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/config.d.ts +8 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +75 -0
- package/dist/config/config.js.map +1 -0
- package/dist/core/fix/confirm.d.ts +21 -0
- package/dist/core/fix/confirm.d.ts.map +1 -0
- package/dist/core/fix/confirm.js +60 -0
- package/dist/core/fix/confirm.js.map +1 -0
- package/dist/core/fix/env-fix.d.ts +40 -0
- package/dist/core/fix/env-fix.d.ts.map +1 -0
- package/dist/core/fix/env-fix.js +186 -0
- package/dist/core/fix/env-fix.js.map +1 -0
- package/dist/core/fix/snapshot.d.ts +30 -0
- package/dist/core/fix/snapshot.d.ts.map +1 -0
- package/dist/core/fix/snapshot.js +186 -0
- package/dist/core/fix/snapshot.js.map +1 -0
- package/dist/core/rules/entropy.d.ts +29 -0
- package/dist/core/rules/entropy.d.ts.map +1 -0
- package/dist/core/rules/entropy.js +117 -0
- package/dist/core/rules/entropy.js.map +1 -0
- package/dist/core/rules/providers.d.ts +12 -0
- package/dist/core/rules/providers.d.ts.map +1 -0
- package/dist/core/rules/providers.js +184 -0
- package/dist/core/rules/providers.js.map +1 -0
- package/dist/core/rules/secret-rules.d.ts +3 -0
- package/dist/core/rules/secret-rules.d.ts.map +1 -0
- package/dist/core/rules/secret-rules.js +205 -0
- package/dist/core/rules/secret-rules.js.map +1 -0
- package/dist/core/scan/env.d.ts +47 -0
- package/dist/core/scan/env.d.ts.map +1 -0
- package/dist/core/scan/env.js +301 -0
- package/dist/core/scan/env.js.map +1 -0
- package/dist/core/scan/framework.d.ts +26 -0
- package/dist/core/scan/framework.d.ts.map +1 -0
- package/dist/core/scan/framework.js +254 -0
- package/dist/core/scan/framework.js.map +1 -0
- package/dist/core/scan/gitignore.d.ts +20 -0
- package/dist/core/scan/gitignore.d.ts.map +1 -0
- package/dist/core/scan/gitignore.js +217 -0
- package/dist/core/scan/gitignore.js.map +1 -0
- package/dist/core/scan/secrets.d.ts +27 -0
- package/dist/core/scan/secrets.d.ts.map +1 -0
- package/dist/core/scan/secrets.js +247 -0
- package/dist/core/scan/secrets.js.map +1 -0
- package/dist/core/score/health.d.ts +29 -0
- package/dist/core/score/health.d.ts.map +1 -0
- package/dist/core/score/health.js +73 -0
- package/dist/core/score/health.js.map +1 -0
- package/dist/core/watch/watcher.d.ts +29 -0
- package/dist/core/watch/watcher.d.ts.map +1 -0
- package/dist/core/watch/watcher.js +176 -0
- package/dist/core/watch/watcher.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/interface.d.ts +12 -0
- package/dist/plugins/interface.d.ts.map +1 -0
- package/dist/plugins/interface.js +91 -0
- package/dist/plugins/interface.js.map +1 -0
- package/dist/plugins/loader.d.ts +10 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +104 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/official/docker.d.ts +4 -0
- package/dist/plugins/official/docker.d.ts.map +1 -0
- package/dist/plugins/official/docker.js +111 -0
- package/dist/plugins/official/docker.js.map +1 -0
- package/dist/plugins/official/terraform.d.ts +4 -0
- package/dist/plugins/official/terraform.d.ts.map +1 -0
- package/dist/plugins/official/terraform.js +131 -0
- package/dist/plugins/official/terraform.js.map +1 -0
- package/dist/types/index.d.ts +158 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/format.d.ts +43 -0
- package/dist/ui/format.d.ts.map +1 -0
- package/dist/ui/format.js +207 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/reporter.d.ts +39 -0
- package/dist/ui/reporter.d.ts.map +1 -0
- package/dist/ui/reporter.js +254 -0
- package/dist/ui/reporter.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// ─── Scan Command ────────────────────────────────────────────────────────────
|
|
2
|
+
// Orchestrates all scanning passes and produces a unified ScanResult.
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promises as fs } from "node:fs";
|
|
5
|
+
import fg from "fast-glob";
|
|
6
|
+
import { loadConfig } from "../config/config.js";
|
|
7
|
+
import { parseEnvFile, findEnvFiles, diffEnvFiles, scanCodeForEnvRefs, findMissingEnvVars, findUnusedEnvVars, } from "../core/scan/env.js";
|
|
8
|
+
import { checkEnvFilesIgnoredWithGit } from "../core/scan/gitignore.js";
|
|
9
|
+
import { scanFileForSecrets, scanGitHistory } from "../core/scan/secrets.js";
|
|
10
|
+
import { detectFramework, checkClientExposedSecrets, } from "../core/scan/framework.js";
|
|
11
|
+
import { calculateHealthScore } from "../core/score/health.js";
|
|
12
|
+
import { loadPlugins } from "../plugins/loader.js";
|
|
13
|
+
import { createPluginContext } from "../plugins/interface.js";
|
|
14
|
+
import { SECRET_RULES } from "../core/rules/secret-rules.js";
|
|
15
|
+
import { reportScanStart, reportScanProgress, reportScanResults, } from "../ui/reporter.js";
|
|
16
|
+
/**
|
|
17
|
+
* Execute a full project scan, returning a ScanResult.
|
|
18
|
+
*
|
|
19
|
+
* 1. Load config
|
|
20
|
+
* 2. Find & parse .env files
|
|
21
|
+
* 3. Detect env mismatches (missing/unused vars)
|
|
22
|
+
* 4. Check .gitignore coverage
|
|
23
|
+
* 5. Scan working tree for secrets
|
|
24
|
+
* 6. Scan git history for secrets
|
|
25
|
+
* 7. Detect framework & client-exposed secrets
|
|
26
|
+
* 8. Run plugins
|
|
27
|
+
* 9. Calculate health score
|
|
28
|
+
* 10. Report results
|
|
29
|
+
*/
|
|
30
|
+
export async function executeScan(projectDir, options = {}) {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
const rootDir = path.resolve(projectDir);
|
|
33
|
+
const config = await loadConfig(rootDir);
|
|
34
|
+
const findings = [];
|
|
35
|
+
// Start spinner unless quiet mode
|
|
36
|
+
const spinner = options.quiet ? null : reportScanStart(rootDir);
|
|
37
|
+
try {
|
|
38
|
+
// ── 1. Find & parse .env files ──────────────────────────────────────
|
|
39
|
+
if (spinner)
|
|
40
|
+
reportScanProgress(spinner, "Parsing .env files…");
|
|
41
|
+
const envFiles = await findEnvFiles(rootDir);
|
|
42
|
+
const parsedEnvFiles = [];
|
|
43
|
+
for (const envFile of envFiles) {
|
|
44
|
+
try {
|
|
45
|
+
const content = await fs.readFile(envFile, "utf-8");
|
|
46
|
+
const parsed = parseEnvFile(content, envFile);
|
|
47
|
+
parsedEnvFiles.push(parsed);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Skip unreadable files
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ── 2. Env mismatch detection ───────────────────────────────────────
|
|
54
|
+
if (spinner)
|
|
55
|
+
reportScanProgress(spinner, "Checking env variable usage…");
|
|
56
|
+
// Find code files
|
|
57
|
+
const codeFiles = await fg(["**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx", "**/*.py", "**/*.rb"], {
|
|
58
|
+
cwd: rootDir,
|
|
59
|
+
ignore: config.ignore,
|
|
60
|
+
onlyFiles: true,
|
|
61
|
+
absolute: true,
|
|
62
|
+
});
|
|
63
|
+
// Scan code for env references and missing vars
|
|
64
|
+
const envRefs = new Set();
|
|
65
|
+
const primaryEnv = parsedEnvFiles[0];
|
|
66
|
+
const definedKeys = primaryEnv ? [...primaryEnv.entries.keys()] : [];
|
|
67
|
+
for (const codeFile of codeFiles) {
|
|
68
|
+
try {
|
|
69
|
+
const content = await fs.readFile(codeFile, "utf-8");
|
|
70
|
+
const refs = scanCodeForEnvRefs(content, codeFile);
|
|
71
|
+
for (const ref of refs)
|
|
72
|
+
envRefs.add(ref);
|
|
73
|
+
if (primaryEnv) {
|
|
74
|
+
const missingFindings = findMissingEnvVars(refs, definedKeys, path.relative(rootDir, codeFile));
|
|
75
|
+
findings.push(...missingFindings);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Skip unreadable files
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Compare env files to find mismatches
|
|
83
|
+
if (parsedEnvFiles.length >= 2) {
|
|
84
|
+
const diffFindings = diffEnvFiles(parsedEnvFiles);
|
|
85
|
+
findings.push(...diffFindings);
|
|
86
|
+
}
|
|
87
|
+
// Find unused env vars
|
|
88
|
+
if (primaryEnv) {
|
|
89
|
+
const unusedFindings = findUnusedEnvVars([...envRefs], [...primaryEnv.entries.values()], path.relative(rootDir, primaryEnv.filePath));
|
|
90
|
+
findings.push(...unusedFindings);
|
|
91
|
+
}
|
|
92
|
+
// ── 3. Check .gitignore coverage ────────────────────────────────────
|
|
93
|
+
if (spinner)
|
|
94
|
+
reportScanProgress(spinner, "Checking .gitignore…");
|
|
95
|
+
let gitignoreContent = "";
|
|
96
|
+
try {
|
|
97
|
+
gitignoreContent = await fs.readFile(path.join(rootDir, ".gitignore"), "utf-8");
|
|
98
|
+
}
|
|
99
|
+
catch { }
|
|
100
|
+
const gitignoreFindings = await checkEnvFilesIgnoredWithGit(rootDir, envFiles);
|
|
101
|
+
findings.push(...gitignoreFindings);
|
|
102
|
+
// ── 4. Scan working tree for secrets ────────────────────────────────
|
|
103
|
+
if (spinner)
|
|
104
|
+
reportScanProgress(spinner, "Scanning for secrets…");
|
|
105
|
+
const scanTargets = await fg(["**/*"], {
|
|
106
|
+
cwd: rootDir,
|
|
107
|
+
ignore: config.ignore,
|
|
108
|
+
onlyFiles: true,
|
|
109
|
+
});
|
|
110
|
+
// Filter to text-like files only
|
|
111
|
+
const textExtensions = new Set([
|
|
112
|
+
".ts",
|
|
113
|
+
".js",
|
|
114
|
+
".tsx",
|
|
115
|
+
".jsx",
|
|
116
|
+
".mjs",
|
|
117
|
+
".cjs",
|
|
118
|
+
".py",
|
|
119
|
+
".rb",
|
|
120
|
+
".go",
|
|
121
|
+
".rs",
|
|
122
|
+
".java",
|
|
123
|
+
".kt",
|
|
124
|
+
".json",
|
|
125
|
+
".yaml",
|
|
126
|
+
".yml",
|
|
127
|
+
".toml",
|
|
128
|
+
".xml",
|
|
129
|
+
".env",
|
|
130
|
+
".cfg",
|
|
131
|
+
".conf",
|
|
132
|
+
".ini",
|
|
133
|
+
".properties",
|
|
134
|
+
".sh",
|
|
135
|
+
".bash",
|
|
136
|
+
".zsh",
|
|
137
|
+
".fish",
|
|
138
|
+
".tf",
|
|
139
|
+
".hcl",
|
|
140
|
+
".dockerfile",
|
|
141
|
+
".md",
|
|
142
|
+
".txt",
|
|
143
|
+
".csv",
|
|
144
|
+
]);
|
|
145
|
+
let scannedFiles = 0;
|
|
146
|
+
for (const file of scanTargets) {
|
|
147
|
+
const ext = path.extname(file).toLowerCase();
|
|
148
|
+
const basename = path.basename(file).toLowerCase();
|
|
149
|
+
// Include dotfiles like .env, .env.local etc.
|
|
150
|
+
const isEnvFile = basename.startsWith(".env");
|
|
151
|
+
if (!isEnvFile && !textExtensions.has(ext) && ext !== "")
|
|
152
|
+
continue;
|
|
153
|
+
const fullPath = path.join(rootDir, file);
|
|
154
|
+
try {
|
|
155
|
+
const stat = await fs.stat(fullPath);
|
|
156
|
+
// Skip files > 1MB
|
|
157
|
+
if (stat.size > 1_048_576)
|
|
158
|
+
continue;
|
|
159
|
+
const content = await fs.readFile(fullPath, "utf-8");
|
|
160
|
+
const secretFindings = scanFileForSecrets(content, file, SECRET_RULES, config.entropyThreshold);
|
|
161
|
+
findings.push(...secretFindings);
|
|
162
|
+
scannedFiles++;
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Skip binary/unreadable files
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// ── 5. Scan git history ─────────────────────────────────────────────
|
|
169
|
+
if (spinner)
|
|
170
|
+
reportScanProgress(spinner, "Scanning git history…");
|
|
171
|
+
try {
|
|
172
|
+
const depth = options.fullHistory ? undefined : config.historyDepth;
|
|
173
|
+
const historyFindings = await scanGitHistory(rootDir, SECRET_RULES, config.entropyThreshold, depth);
|
|
174
|
+
findings.push(...historyFindings);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Not a git repo or git not available — skip
|
|
178
|
+
}
|
|
179
|
+
// ── 6. Detect framework & client-exposed secrets ────────────────────
|
|
180
|
+
if (spinner)
|
|
181
|
+
reportScanProgress(spinner, "Detecting framework…");
|
|
182
|
+
let framework;
|
|
183
|
+
try {
|
|
184
|
+
const detected = await detectFramework(rootDir);
|
|
185
|
+
framework = detected || undefined;
|
|
186
|
+
if (framework && parsedEnvFiles.length > 0) {
|
|
187
|
+
const exposedFindings = checkClientExposedSecrets(parsedEnvFiles, framework, SECRET_RULES, config.entropyThreshold);
|
|
188
|
+
findings.push(...exposedFindings);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Framework detection failed — non-critical
|
|
193
|
+
}
|
|
194
|
+
// ── 7. Load and run plugins ─────────────────────────────────────────
|
|
195
|
+
if (spinner)
|
|
196
|
+
reportScanProgress(spinner, "Running plugins…");
|
|
197
|
+
try {
|
|
198
|
+
const plugins = await loadPlugins(config, rootDir);
|
|
199
|
+
if (plugins.length > 0) {
|
|
200
|
+
const pluginContext = await createPluginContext(rootDir, config);
|
|
201
|
+
for (const plugin of plugins) {
|
|
202
|
+
try {
|
|
203
|
+
const result = await plugin.check(pluginContext);
|
|
204
|
+
findings.push(...result.findings);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// Plugin error — skip silently
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// Plugin loading failed — non-critical
|
|
214
|
+
}
|
|
215
|
+
// ── 8. Apply severity overrides ─────────────────────────────────────
|
|
216
|
+
for (const finding of findings) {
|
|
217
|
+
if (finding.ruleId) {
|
|
218
|
+
const override = config.severityOverrides[finding.ruleId];
|
|
219
|
+
if (override) {
|
|
220
|
+
finding.severity = override;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// ── 9. Filter by severity if requested ──────────────────────────────
|
|
225
|
+
let filteredFindings = findings;
|
|
226
|
+
if (options.severity) {
|
|
227
|
+
const severityOrder = {
|
|
228
|
+
critical: 0,
|
|
229
|
+
warning: 1,
|
|
230
|
+
info: 2,
|
|
231
|
+
};
|
|
232
|
+
const minLevel = severityOrder[options.severity];
|
|
233
|
+
filteredFindings = findings.filter((f) => severityOrder[f.severity] <= minLevel);
|
|
234
|
+
}
|
|
235
|
+
// ── 10. Calculate health score ──────────────────────────────────────
|
|
236
|
+
const { score, grade } = calculateHealthScore(filteredFindings);
|
|
237
|
+
const duration = Date.now() - start;
|
|
238
|
+
const result = {
|
|
239
|
+
findings: filteredFindings,
|
|
240
|
+
healthScore: score,
|
|
241
|
+
grade,
|
|
242
|
+
timestamp: new Date(),
|
|
243
|
+
scannedFiles,
|
|
244
|
+
framework,
|
|
245
|
+
duration,
|
|
246
|
+
};
|
|
247
|
+
// ── 11. Report ──────────────────────────────────────────────────────
|
|
248
|
+
if (spinner)
|
|
249
|
+
spinner.stop();
|
|
250
|
+
if (options.json) {
|
|
251
|
+
console.log(JSON.stringify(result, null, 2));
|
|
252
|
+
}
|
|
253
|
+
else if (!options.quiet) {
|
|
254
|
+
reportScanResults(result, {
|
|
255
|
+
fun: options.fun ?? config.funMode,
|
|
256
|
+
verbose: options.verbose,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
if (spinner)
|
|
263
|
+
spinner.fail("Scan failed");
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execute the `bilt undo` command.
|
|
3
|
+
*
|
|
4
|
+
* 1. List available snapshots
|
|
5
|
+
* 2. Get latest snapshot
|
|
6
|
+
* 3. Show preview of what will be restored
|
|
7
|
+
* 4. Require confirmation
|
|
8
|
+
* 5. Restore snapshot
|
|
9
|
+
* 6. Report success
|
|
10
|
+
*/
|
|
11
|
+
export declare function executeUndo(projectDir: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=undo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo.d.ts","sourceRoot":"","sources":["../../src/commands/undo.ts"],"names":[],"mappings":"AAeA;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFnE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// ─── Undo Command ────────────────────────────────────────────────────────────
|
|
2
|
+
// Restore the latest snapshot to revert changes made by `bilt fix`.
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { getLatestSnapshot, listSnapshots, restoreSnapshot, } from "../core/fix/snapshot.js";
|
|
6
|
+
import { requireSimpleConfirmation } from "../core/fix/confirm.js";
|
|
7
|
+
import { reportUndoComplete } from "../ui/reporter.js";
|
|
8
|
+
import { formatDiff } from "../ui/format.js";
|
|
9
|
+
import { promises as fs } from "node:fs";
|
|
10
|
+
/**
|
|
11
|
+
* Execute the `bilt undo` command.
|
|
12
|
+
*
|
|
13
|
+
* 1. List available snapshots
|
|
14
|
+
* 2. Get latest snapshot
|
|
15
|
+
* 3. Show preview of what will be restored
|
|
16
|
+
* 4. Require confirmation
|
|
17
|
+
* 5. Restore snapshot
|
|
18
|
+
* 6. Report success
|
|
19
|
+
*/
|
|
20
|
+
export async function executeUndo(projectDir) {
|
|
21
|
+
const rootDir = path.resolve(projectDir);
|
|
22
|
+
// ── List snapshots ──────────────────────────────────────────────────
|
|
23
|
+
const snapshots = await listSnapshots(rootDir);
|
|
24
|
+
if (snapshots.length === 0) {
|
|
25
|
+
console.log("");
|
|
26
|
+
console.log(chalk.yellow(" ⚠ No snapshots found. Nothing to undo."));
|
|
27
|
+
console.log(chalk.dim(" Snapshots are created automatically when `bilt fix` or `bilt init` makes changes."));
|
|
28
|
+
console.log("");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// ── Get latest snapshot ─────────────────────────────────────────────
|
|
32
|
+
const snapshot = await getLatestSnapshot(rootDir);
|
|
33
|
+
if (!snapshot) {
|
|
34
|
+
console.log("");
|
|
35
|
+
console.log(chalk.yellow(" ⚠ Could not load the latest snapshot."));
|
|
36
|
+
console.log("");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// ── Preview changes ─────────────────────────────────────────────────
|
|
40
|
+
console.log("");
|
|
41
|
+
console.log(chalk.bold(` ⏪ Snapshot: ${chalk.cyan(snapshot.id)}`));
|
|
42
|
+
console.log(chalk.dim(` ${snapshot.description}`));
|
|
43
|
+
console.log(chalk.dim(` Created: ${new Date(snapshot.timestamp).toLocaleString()}`));
|
|
44
|
+
console.log("");
|
|
45
|
+
console.log(chalk.bold(" Files to restore:"));
|
|
46
|
+
for (const file of snapshot.files) {
|
|
47
|
+
const fullPath = path.join(rootDir, file.path);
|
|
48
|
+
let currentContent = "";
|
|
49
|
+
try {
|
|
50
|
+
currentContent = await fs.readFile(fullPath, "utf-8");
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
currentContent = "";
|
|
54
|
+
}
|
|
55
|
+
const hasChanged = currentContent !== file.content;
|
|
56
|
+
if (hasChanged) {
|
|
57
|
+
console.log(chalk.yellow(` ↻ ${file.path}`));
|
|
58
|
+
// Show brief diff
|
|
59
|
+
const diff = formatDiff(currentContent, file.content);
|
|
60
|
+
const diffLines = diff.split("\n").slice(0, 8);
|
|
61
|
+
for (const line of diffLines) {
|
|
62
|
+
console.log(` ${line}`);
|
|
63
|
+
}
|
|
64
|
+
if (diff.split("\n").length > 8) {
|
|
65
|
+
console.log(chalk.dim(` … and more`));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.log(chalk.dim(` ✓ ${file.path} (unchanged)`));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
console.log("");
|
|
73
|
+
// ── Confirm ─────────────────────────────────────────────────────────
|
|
74
|
+
const confirmed = await requireSimpleConfirmation({
|
|
75
|
+
id: "undo",
|
|
76
|
+
description: `Restore ${snapshot.files.length} file(s) from snapshot`,
|
|
77
|
+
type: "destructive",
|
|
78
|
+
findingId: "undo",
|
|
79
|
+
apply: async () => true,
|
|
80
|
+
});
|
|
81
|
+
if (!confirmed) {
|
|
82
|
+
console.log(chalk.dim(" Undo cancelled."));
|
|
83
|
+
console.log("");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// ── Restore ─────────────────────────────────────────────────────────
|
|
87
|
+
await restoreSnapshot(snapshot.id, rootDir);
|
|
88
|
+
reportUndoComplete(snapshot);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=undo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo.js","sourceRoot":"","sources":["../../src/commands/undo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WatchOptions } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute the `bilt watch` command.
|
|
4
|
+
*
|
|
5
|
+
* 1. Start file watcher on the project directory
|
|
6
|
+
* 2. On file changes: scan for secrets and report findings
|
|
7
|
+
* 3. Handle SIGINT for graceful shutdown
|
|
8
|
+
*/
|
|
9
|
+
export declare function executeWatch(projectDir: string, options?: WatchOptions): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,mBAAmB,CAAC;AAKlE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CA0Df"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// ─── Watch Command ───────────────────────────────────────────────────────────
|
|
2
|
+
// Real-time file monitoring with instant secret & env scanning.
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { loadConfig } from "../config/config.js";
|
|
6
|
+
import { startWatcher, stopWatcher } from "../core/watch/watcher.js";
|
|
7
|
+
import { reportWatchEvent } from "../ui/reporter.js";
|
|
8
|
+
/**
|
|
9
|
+
* Execute the `bilt watch` command.
|
|
10
|
+
*
|
|
11
|
+
* 1. Start file watcher on the project directory
|
|
12
|
+
* 2. On file changes: scan for secrets and report findings
|
|
13
|
+
* 3. Handle SIGINT for graceful shutdown
|
|
14
|
+
*/
|
|
15
|
+
export async function executeWatch(projectDir, options = {}) {
|
|
16
|
+
const rootDir = path.resolve(projectDir);
|
|
17
|
+
const config = await loadConfig(rootDir);
|
|
18
|
+
// ── Status banner ───────────────────────────────────────────────────
|
|
19
|
+
if (!options.quiet) {
|
|
20
|
+
console.log("");
|
|
21
|
+
console.log(chalk.cyan.bold(" 👁️ Bilt Watch Mode"));
|
|
22
|
+
console.log(chalk.dim(` Monitoring ${rootDir} for changes…`));
|
|
23
|
+
console.log(chalk.dim(" Press Ctrl+C to stop."));
|
|
24
|
+
console.log("");
|
|
25
|
+
}
|
|
26
|
+
// ── Start watcher ──────────────────────────────────────────────────
|
|
27
|
+
const watcher = startWatcher(rootDir, config, (event) => {
|
|
28
|
+
// Only report if there are findings or the file was deleted
|
|
29
|
+
if (event.findings.length > 0 || event.type === "unlink") {
|
|
30
|
+
// Map absolute path back to relative path for formatting
|
|
31
|
+
const relativePath = path.relative(rootDir, event.file);
|
|
32
|
+
const relativeFindings = event.findings.map((f) => ({
|
|
33
|
+
...f,
|
|
34
|
+
file: path.relative(rootDir, f.file),
|
|
35
|
+
}));
|
|
36
|
+
reportWatchEvent({
|
|
37
|
+
...event,
|
|
38
|
+
file: relativePath,
|
|
39
|
+
findings: relativeFindings,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// ── Graceful shutdown ──────────────────────────────────────────────
|
|
44
|
+
const cleanup = async () => {
|
|
45
|
+
if (!options.quiet) {
|
|
46
|
+
console.log("");
|
|
47
|
+
console.log(chalk.dim(" Stopping watcher…"));
|
|
48
|
+
}
|
|
49
|
+
await stopWatcher(watcher);
|
|
50
|
+
if (!options.quiet) {
|
|
51
|
+
console.log(chalk.green(" ✓ Watcher stopped."));
|
|
52
|
+
console.log("");
|
|
53
|
+
}
|
|
54
|
+
process.exit(0);
|
|
55
|
+
};
|
|
56
|
+
process.on("SIGINT", () => {
|
|
57
|
+
void cleanup();
|
|
58
|
+
});
|
|
59
|
+
process.on("SIGTERM", () => {
|
|
60
|
+
void cleanup();
|
|
61
|
+
});
|
|
62
|
+
// Keep the process running
|
|
63
|
+
await new Promise(() => {
|
|
64
|
+
// This promise intentionally never resolves — the process stays alive
|
|
65
|
+
// until SIGINT/SIGTERM.
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BiltConfig } from "../types/index.js";
|
|
2
|
+
export declare const DEFAULT_CONFIG: BiltConfig;
|
|
3
|
+
/**
|
|
4
|
+
* Load and merge user configuration with defaults.
|
|
5
|
+
* If no config file exists, returns defaults (zero-config).
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadConfig(searchFrom?: string): Promise<BiltConfig>;
|
|
8
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,eAAO,MAAM,cAAc,EAAE,UAsB5B,CAAC;AAoBF;;;GAGG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA+BzE"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
2
|
+
// ─── Default Configuration (Zero-Config) ────────────────────────────────────
|
|
3
|
+
export const DEFAULT_CONFIG = {
|
|
4
|
+
ignore: [
|
|
5
|
+
"node_modules/**",
|
|
6
|
+
".git/**",
|
|
7
|
+
"dist/**",
|
|
8
|
+
"build/**",
|
|
9
|
+
"coverage/**",
|
|
10
|
+
".bilt/**",
|
|
11
|
+
"*.min.js",
|
|
12
|
+
"*.min.css",
|
|
13
|
+
"*.map",
|
|
14
|
+
"*.lock",
|
|
15
|
+
"package-lock.json",
|
|
16
|
+
"yarn.lock",
|
|
17
|
+
"pnpm-lock.yaml",
|
|
18
|
+
],
|
|
19
|
+
severityOverrides: {},
|
|
20
|
+
plugins: [],
|
|
21
|
+
entropyThreshold: 4.5,
|
|
22
|
+
historyDepth: 10,
|
|
23
|
+
customRules: [],
|
|
24
|
+
funMode: false,
|
|
25
|
+
};
|
|
26
|
+
// ─── Config Loader ───────────────────────────────────────────────────────────
|
|
27
|
+
const explorer = cosmiconfig("bilt", {
|
|
28
|
+
searchPlaces: [
|
|
29
|
+
".biltrc",
|
|
30
|
+
".biltrc.json",
|
|
31
|
+
".biltrc.yaml",
|
|
32
|
+
".biltrc.yml",
|
|
33
|
+
".biltrc.js",
|
|
34
|
+
".biltrc.cjs",
|
|
35
|
+
".biltrc.mjs",
|
|
36
|
+
"bilt.config.js",
|
|
37
|
+
"bilt.config.cjs",
|
|
38
|
+
"bilt.config.mjs",
|
|
39
|
+
"bilt.config.ts",
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Load and merge user configuration with defaults.
|
|
44
|
+
* If no config file exists, returns defaults (zero-config).
|
|
45
|
+
*/
|
|
46
|
+
export async function loadConfig(searchFrom) {
|
|
47
|
+
try {
|
|
48
|
+
const result = await explorer.search(searchFrom);
|
|
49
|
+
if (!result || result.isEmpty) {
|
|
50
|
+
return { ...DEFAULT_CONFIG };
|
|
51
|
+
}
|
|
52
|
+
const userConfig = result.config;
|
|
53
|
+
return {
|
|
54
|
+
ignore: userConfig.ignore
|
|
55
|
+
? [...DEFAULT_CONFIG.ignore, ...userConfig.ignore]
|
|
56
|
+
: [...DEFAULT_CONFIG.ignore],
|
|
57
|
+
severityOverrides: {
|
|
58
|
+
...DEFAULT_CONFIG.severityOverrides,
|
|
59
|
+
...userConfig.severityOverrides,
|
|
60
|
+
},
|
|
61
|
+
plugins: userConfig.plugins ?? DEFAULT_CONFIG.plugins,
|
|
62
|
+
entropyThreshold: userConfig.entropyThreshold ?? DEFAULT_CONFIG.entropyThreshold,
|
|
63
|
+
historyDepth: userConfig.historyDepth ?? DEFAULT_CONFIG.historyDepth,
|
|
64
|
+
customRules: userConfig.customRules
|
|
65
|
+
? [...DEFAULT_CONFIG.customRules, ...userConfig.customRules]
|
|
66
|
+
: [...DEFAULT_CONFIG.customRules],
|
|
67
|
+
funMode: userConfig.funMode ?? DEFAULT_CONFIG.funMode,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// If config loading fails, silently use defaults (zero-config philosophy)
|
|
72
|
+
return { ...DEFAULT_CONFIG };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,+EAA+E;AAE/E,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,MAAM,EAAE;QACN,iBAAiB;QACjB,SAAS;QACT,SAAS;QACT,UAAU;QACV,aAAa;QACb,UAAU;QACV,UAAU;QACV,WAAW;QACX,OAAO;QACP,QAAQ;QACR,mBAAmB;QACnB,WAAW;QACX,gBAAgB;KACjB;IACD,iBAAiB,EAAE,EAAE;IACrB,OAAO,EAAE,EAAE;IACX,gBAAgB,EAAE,GAAG;IACrB,YAAY,EAAE,EAAE;IAChB,WAAW,EAAE,EAAE;IACf,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,gFAAgF;AAEhF,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE;IACnC,YAAY,EAAE;QACZ,SAAS;QACT,cAAc;QACd,cAAc;QACd,aAAa;QACb,YAAY;QACZ,aAAa;QACb,aAAa;QACb,gBAAgB;QAChB,iBAAiB;QACjB,iBAAiB;QACjB,gBAAgB;KACjB;CACF,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAmB;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,MAA6B,CAAC;QAExD,OAAO;YACL,MAAM,EAAE,UAAU,CAAC,MAAM;gBACvB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC;gBAClD,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;YAC9B,iBAAiB,EAAE;gBACjB,GAAG,cAAc,CAAC,iBAAiB;gBACnC,GAAG,UAAU,CAAC,iBAAiB;aAChC;YACD,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO;YACrD,gBAAgB,EACd,UAAU,CAAC,gBAAgB,IAAI,cAAc,CAAC,gBAAgB;YAChE,YAAY,EAAE,UAAU,CAAC,YAAY,IAAI,cAAc,CAAC,YAAY;YACpE,WAAW,EAAE,UAAU,CAAC,WAAW;gBACjC,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC;gBAC5D,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC;YACnC,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO;SACtD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FixAction } from "../../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Prompt the user to type the filename to confirm an **irreversible** action.
|
|
4
|
+
*
|
|
5
|
+
* Used for actions like permanently deleting a file or rewriting git history
|
|
6
|
+
* where a simple y/n is not enough assurance.
|
|
7
|
+
*
|
|
8
|
+
* @param action The fix action being applied.
|
|
9
|
+
* @param fileName The filename the user must type to confirm.
|
|
10
|
+
* @returns `true` if the user typed the correct filename, `false` otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export declare function requireTypedConfirmation(action: FixAction, fileName: string): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Prompt the user for a simple y/n confirmation for a **destructive**
|
|
15
|
+
* action.
|
|
16
|
+
*
|
|
17
|
+
* @param action The fix action being applied.
|
|
18
|
+
* @returns `true` if the user confirms, `false` otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export declare function requireSimpleConfirmation(action: FixAction): Promise<boolean>;
|
|
21
|
+
//# sourceMappingURL=confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../../src/core/fix/confirm.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAOtD;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAkBlB;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,SAAS,GAChB,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
|