@runhalo/cli 0.1.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/dist/index.d.ts +46 -0
- package/dist/index.js +632 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Halo CLI - Child Safety Compliance Scanner
|
|
4
|
+
* Usage: runhalo scan <path> [options]
|
|
5
|
+
*/
|
|
6
|
+
import { HaloEngine, Violation, ScanResult, EngineConfig } from '@runhalo/engine';
|
|
7
|
+
type OutputFormat = 'json' | 'sarif' | 'text';
|
|
8
|
+
interface CLIOptions {
|
|
9
|
+
format: OutputFormat;
|
|
10
|
+
include: string[];
|
|
11
|
+
exclude: string[];
|
|
12
|
+
rules: string[];
|
|
13
|
+
severity: string[];
|
|
14
|
+
output: string;
|
|
15
|
+
verbose: boolean;
|
|
16
|
+
ethicalPreview: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format violations as SARIF output
|
|
20
|
+
*/
|
|
21
|
+
declare function formatSARIF(results: ScanResult[], rules: any[]): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format violations as JSON output
|
|
24
|
+
*/
|
|
25
|
+
declare function formatJSON(results: ScanResult[]): string;
|
|
26
|
+
/**
|
|
27
|
+
* Format violations as human-readable text
|
|
28
|
+
*/
|
|
29
|
+
declare function formatText(results: ScanResult[], verbose?: boolean, fileCount?: number): string;
|
|
30
|
+
/**
|
|
31
|
+
* Create a Halo engine instance
|
|
32
|
+
*/
|
|
33
|
+
declare function createEngine(config?: EngineConfig): HaloEngine;
|
|
34
|
+
/**
|
|
35
|
+
* Scan a single file
|
|
36
|
+
*/
|
|
37
|
+
declare function scanFile(filePath: string, content?: string): Violation[];
|
|
38
|
+
/**
|
|
39
|
+
* Scan a directory
|
|
40
|
+
*/
|
|
41
|
+
declare function scanDirectory(dirPath: string, config?: EngineConfig): Promise<ScanResult[]>;
|
|
42
|
+
/**
|
|
43
|
+
* Main scan function
|
|
44
|
+
*/
|
|
45
|
+
declare function scan(paths: string[], options: CLIOptions): Promise<number>;
|
|
46
|
+
export { scan, scanFile, scanDirectory, createEngine, formatSARIF, formatJSON, formatText };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Halo CLI - Child Safety Compliance Scanner
|
|
5
|
+
* Usage: runhalo scan <path> [options]
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.scan = scan;
|
|
42
|
+
exports.scanFile = scanFile;
|
|
43
|
+
exports.scanDirectory = scanDirectory;
|
|
44
|
+
exports.createEngine = createEngine;
|
|
45
|
+
exports.formatSARIF = formatSARIF;
|
|
46
|
+
exports.formatJSON = formatJSON;
|
|
47
|
+
exports.formatText = formatText;
|
|
48
|
+
const commander_1 = require("commander");
|
|
49
|
+
const glob_1 = require("glob");
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const engine_1 = require("@runhalo/engine");
|
|
53
|
+
// CLI configuration
|
|
54
|
+
const program = new commander_1.Command();
|
|
55
|
+
/**
|
|
56
|
+
* Get default file patterns to scan
|
|
57
|
+
*/
|
|
58
|
+
function getDefaultPatterns() {
|
|
59
|
+
return [
|
|
60
|
+
'**/*.ts',
|
|
61
|
+
'**/*.js',
|
|
62
|
+
'**/*.tsx',
|
|
63
|
+
'**/*.jsx',
|
|
64
|
+
'**/*.py',
|
|
65
|
+
'**/*.swift',
|
|
66
|
+
'**/*.java',
|
|
67
|
+
'**/*.kt',
|
|
68
|
+
'**/*.sql',
|
|
69
|
+
'**/*.html',
|
|
70
|
+
'**/*.vue',
|
|
71
|
+
'**/*.svelte',
|
|
72
|
+
// Added Phase B: languages previously missing (C++, C#, PHP, QML)
|
|
73
|
+
'**/*.php',
|
|
74
|
+
'**/*.cpp',
|
|
75
|
+
'**/*.h',
|
|
76
|
+
'**/*.hpp',
|
|
77
|
+
'**/*.cs',
|
|
78
|
+
'**/*.qml'
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get default exclusion patterns
|
|
83
|
+
*/
|
|
84
|
+
function getDefaultExcludePatterns() {
|
|
85
|
+
return [
|
|
86
|
+
// Package and build artifacts
|
|
87
|
+
'node_modules/**',
|
|
88
|
+
'dist/**',
|
|
89
|
+
'build/**',
|
|
90
|
+
'.git/**',
|
|
91
|
+
'coverage/**',
|
|
92
|
+
'.next/**',
|
|
93
|
+
'.svelte-kit/**',
|
|
94
|
+
'.nuxt/**',
|
|
95
|
+
// Minified and bundled files (major FP source — vendor code is not your code)
|
|
96
|
+
'**/*.min.js',
|
|
97
|
+
'**/*.min.mjs',
|
|
98
|
+
'**/*.bundle.js',
|
|
99
|
+
'**/*.chunk.js',
|
|
100
|
+
// Vendor and static asset directories
|
|
101
|
+
'**/vendor/**',
|
|
102
|
+
'**/static/js/**',
|
|
103
|
+
'**/public/js/**',
|
|
104
|
+
'**/assets/js/**',
|
|
105
|
+
// Test files (compliance scans shouldn't flag test code)
|
|
106
|
+
'**/test/**',
|
|
107
|
+
'**/tests/**',
|
|
108
|
+
'**/__tests__/**',
|
|
109
|
+
'**/__mocks__/**',
|
|
110
|
+
'**/spec/**',
|
|
111
|
+
'**/fixtures/**',
|
|
112
|
+
'**/testing/**',
|
|
113
|
+
'**/testdata/**',
|
|
114
|
+
'**/*.test.ts',
|
|
115
|
+
'**/*.test.js',
|
|
116
|
+
'**/*.test.tsx',
|
|
117
|
+
'**/*.test.jsx',
|
|
118
|
+
'**/*.spec.ts',
|
|
119
|
+
'**/*.spec.js',
|
|
120
|
+
'**/*.spec.tsx',
|
|
121
|
+
'**/*.spec.jsx',
|
|
122
|
+
'**/test_*.py',
|
|
123
|
+
'**/conftest.py',
|
|
124
|
+
'**/*_test.py',
|
|
125
|
+
'**/*_test.go',
|
|
126
|
+
// Lock files
|
|
127
|
+
'**/package-lock.json',
|
|
128
|
+
'**/yarn.lock',
|
|
129
|
+
'**/pnpm-lock.yaml'
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Format violations as SARIF output
|
|
134
|
+
*/
|
|
135
|
+
function formatSARIF(results, rules) {
|
|
136
|
+
const sarif = {
|
|
137
|
+
version: '2.1.0',
|
|
138
|
+
$schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
|
|
139
|
+
runs: [{
|
|
140
|
+
tool: {
|
|
141
|
+
driver: {
|
|
142
|
+
name: 'Halo',
|
|
143
|
+
version: '1.0.0',
|
|
144
|
+
informationUri: 'https://runhalo.dev',
|
|
145
|
+
rules: rules.map(r => ({
|
|
146
|
+
id: r.id,
|
|
147
|
+
name: r.name,
|
|
148
|
+
shortDescription: { text: r.description },
|
|
149
|
+
helpUri: `https://runhalo.dev/rules/${r.id}`,
|
|
150
|
+
defaultConfiguration: { level: r.severity }
|
|
151
|
+
}))
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
results: results.flatMap(result => result.violations.map(v => ({
|
|
155
|
+
ruleId: v.ruleId,
|
|
156
|
+
level: v.severity === 'critical' || v.severity === 'high' ? 'error' : 'warning',
|
|
157
|
+
message: { text: v.message },
|
|
158
|
+
locations: [{
|
|
159
|
+
physicalLocation: {
|
|
160
|
+
artifactLocation: {
|
|
161
|
+
uri: result.filePath,
|
|
162
|
+
uriBaseId: 'SRCROOT'
|
|
163
|
+
},
|
|
164
|
+
region: {
|
|
165
|
+
startLine: v.line,
|
|
166
|
+
startColumn: v.column
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}]
|
|
170
|
+
})))
|
|
171
|
+
}]
|
|
172
|
+
};
|
|
173
|
+
return JSON.stringify(sarif, null, 2);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Format violations as JSON output
|
|
177
|
+
*/
|
|
178
|
+
function formatJSON(results) {
|
|
179
|
+
const output = {
|
|
180
|
+
version: '1.0.0',
|
|
181
|
+
scannedAt: new Date().toISOString(),
|
|
182
|
+
totalFiles: results.length,
|
|
183
|
+
totalViolations: results.reduce((sum, r) => sum + r.violations.length, 0),
|
|
184
|
+
results: results
|
|
185
|
+
};
|
|
186
|
+
return JSON.stringify(output, null, 2);
|
|
187
|
+
}
|
|
188
|
+
// ANSI color codes for terminal output
|
|
189
|
+
const colors = {
|
|
190
|
+
reset: '\x1b[0m',
|
|
191
|
+
bold: '\x1b[1m',
|
|
192
|
+
dim: '\x1b[2m',
|
|
193
|
+
red: '\x1b[31m',
|
|
194
|
+
yellow: '\x1b[33m',
|
|
195
|
+
blue: '\x1b[34m',
|
|
196
|
+
cyan: '\x1b[36m',
|
|
197
|
+
white: '\x1b[37m',
|
|
198
|
+
bgRed: '\x1b[41m',
|
|
199
|
+
bgYellow: '\x1b[43m',
|
|
200
|
+
bgBlue: '\x1b[44m',
|
|
201
|
+
magenta: '\x1b[35m',
|
|
202
|
+
};
|
|
203
|
+
// Detect if color should be used (respect NO_COLOR env and pipe detection)
|
|
204
|
+
const useColor = !process.env.NO_COLOR && process.stdout.isTTY !== false;
|
|
205
|
+
function c(color, text) {
|
|
206
|
+
return useColor ? `${color}${text}${colors.reset}` : text;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Format violations as human-readable text
|
|
210
|
+
*/
|
|
211
|
+
function formatText(results, verbose = false, fileCount = 0) {
|
|
212
|
+
let output = '';
|
|
213
|
+
let totalViolations = 0;
|
|
214
|
+
let criticalCount = 0;
|
|
215
|
+
let highCount = 0;
|
|
216
|
+
let mediumCount = 0;
|
|
217
|
+
let lowCount = 0;
|
|
218
|
+
let filesWithViolations = 0;
|
|
219
|
+
for (const result of results) {
|
|
220
|
+
if (result.violations.length === 0)
|
|
221
|
+
continue;
|
|
222
|
+
filesWithViolations++;
|
|
223
|
+
totalViolations += result.violations.length;
|
|
224
|
+
// Count by severity
|
|
225
|
+
for (const v of result.violations) {
|
|
226
|
+
switch (v.severity) {
|
|
227
|
+
case 'critical':
|
|
228
|
+
criticalCount++;
|
|
229
|
+
break;
|
|
230
|
+
case 'high':
|
|
231
|
+
highCount++;
|
|
232
|
+
break;
|
|
233
|
+
case 'medium':
|
|
234
|
+
mediumCount++;
|
|
235
|
+
break;
|
|
236
|
+
case 'low':
|
|
237
|
+
lowCount++;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
output += `\n${c(colors.bold, result.filePath)}\n`;
|
|
242
|
+
for (const violation of result.violations) {
|
|
243
|
+
// Severity tag with color
|
|
244
|
+
let severityTag;
|
|
245
|
+
switch (violation.severity) {
|
|
246
|
+
case 'critical':
|
|
247
|
+
severityTag = c(colors.red + colors.bold, 'CRITICAL');
|
|
248
|
+
break;
|
|
249
|
+
case 'high':
|
|
250
|
+
severityTag = c(colors.yellow + colors.bold, 'HIGH');
|
|
251
|
+
break;
|
|
252
|
+
case 'medium':
|
|
253
|
+
severityTag = c(colors.blue, 'MEDIUM');
|
|
254
|
+
break;
|
|
255
|
+
default:
|
|
256
|
+
severityTag = c(colors.dim, 'LOW');
|
|
257
|
+
}
|
|
258
|
+
// Always show line:column (developer-standard format)
|
|
259
|
+
const location = c(colors.dim, `${violation.line}:${violation.column}`);
|
|
260
|
+
output += ` ${location} ${severityTag} ${c(colors.cyan, violation.ruleId)}\n`;
|
|
261
|
+
output += ` ${c(colors.dim, '│')} ${violation.message}\n`;
|
|
262
|
+
if (verbose) {
|
|
263
|
+
output += ` ${c(colors.dim, '│')} ${c(colors.magenta, '💡')} ${violation.fixSuggestion}\n`;
|
|
264
|
+
if (violation.penalty) {
|
|
265
|
+
output += ` ${c(colors.dim, '│')} ${c(colors.red, '⚠')} Penalty: ${violation.penalty}\n`;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
output += '\n';
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (totalViolations === 0) {
|
|
272
|
+
const scannedMsg = fileCount > 0 ? ` (${fileCount} files scanned)` : '';
|
|
273
|
+
return `${c(colors.bold, '✅ No COPPA issues detected!')}${scannedMsg}\n`;
|
|
274
|
+
}
|
|
275
|
+
// Summary header
|
|
276
|
+
let header = `\n${c(colors.bold, `⚠ Found ${totalViolations} issue(s)`)}`;
|
|
277
|
+
header += ` across ${filesWithViolations} file(s)`;
|
|
278
|
+
if (fileCount > 0) {
|
|
279
|
+
header += ` (${fileCount} files scanned)`;
|
|
280
|
+
}
|
|
281
|
+
header += '\n';
|
|
282
|
+
// Severity breakdown
|
|
283
|
+
const parts = [];
|
|
284
|
+
if (criticalCount > 0)
|
|
285
|
+
parts.push(c(colors.red + colors.bold, `${criticalCount} critical`));
|
|
286
|
+
if (highCount > 0)
|
|
287
|
+
parts.push(c(colors.yellow + colors.bold, `${highCount} high`));
|
|
288
|
+
if (mediumCount > 0)
|
|
289
|
+
parts.push(c(colors.blue, `${mediumCount} medium`));
|
|
290
|
+
if (lowCount > 0)
|
|
291
|
+
parts.push(c(colors.dim, `${lowCount} low`));
|
|
292
|
+
header += ` ${parts.join(c(colors.dim, ' · '))}\n`;
|
|
293
|
+
return header + output;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Load .haloignore from a directory (walks up to find it)
|
|
297
|
+
*/
|
|
298
|
+
function loadHaloignore(startDir) {
|
|
299
|
+
let dir = path.resolve(startDir);
|
|
300
|
+
const root = path.parse(dir).root;
|
|
301
|
+
while (dir !== root) {
|
|
302
|
+
const ignorePath = path.join(dir, '.haloignore');
|
|
303
|
+
if (fs.existsSync(ignorePath)) {
|
|
304
|
+
try {
|
|
305
|
+
const content = fs.readFileSync(ignorePath, 'utf-8');
|
|
306
|
+
return (0, engine_1.parseHaloignore)(content);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
dir = path.dirname(dir);
|
|
313
|
+
}
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Create a Halo engine instance
|
|
318
|
+
*/
|
|
319
|
+
function createEngine(config) {
|
|
320
|
+
return new engine_1.HaloEngine(config);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Scan a single file
|
|
324
|
+
*/
|
|
325
|
+
function scanFile(filePath, content) {
|
|
326
|
+
const engine = new engine_1.HaloEngine();
|
|
327
|
+
const fileContent = content || fs.readFileSync(filePath, 'utf-8');
|
|
328
|
+
return engine.scanFile(filePath, fileContent);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Scan a directory
|
|
332
|
+
*/
|
|
333
|
+
async function scanDirectory(dirPath, config) {
|
|
334
|
+
const engine = new engine_1.HaloEngine(config);
|
|
335
|
+
const results = [];
|
|
336
|
+
const stats = fs.statSync(dirPath);
|
|
337
|
+
if (stats.isDirectory()) {
|
|
338
|
+
const patterns = getDefaultPatterns();
|
|
339
|
+
const excludes = getDefaultExcludePatterns();
|
|
340
|
+
let allFiles = [];
|
|
341
|
+
for (const pattern of patterns) {
|
|
342
|
+
const fullPattern = path.join(dirPath, pattern);
|
|
343
|
+
const files = await (0, glob_1.glob)(fullPattern, {
|
|
344
|
+
ignore: excludes,
|
|
345
|
+
absolute: true
|
|
346
|
+
});
|
|
347
|
+
allFiles.push(...files);
|
|
348
|
+
}
|
|
349
|
+
const uniqueFiles = [...new Set(allFiles)];
|
|
350
|
+
for (const filePath of uniqueFiles) {
|
|
351
|
+
try {
|
|
352
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
353
|
+
const violations = engine.scanFile(filePath, content);
|
|
354
|
+
results.push({
|
|
355
|
+
filePath,
|
|
356
|
+
violations,
|
|
357
|
+
scannedAt: new Date().toISOString(),
|
|
358
|
+
totalViolations: violations.length,
|
|
359
|
+
suppressedCount: 0
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
catch (err) {
|
|
363
|
+
// Skip files that can't be read
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
const content = fs.readFileSync(dirPath, 'utf-8');
|
|
369
|
+
const violations = engine.scanFile(dirPath, content);
|
|
370
|
+
results.push({
|
|
371
|
+
filePath: dirPath,
|
|
372
|
+
violations,
|
|
373
|
+
scannedAt: new Date().toISOString(),
|
|
374
|
+
totalViolations: violations.length,
|
|
375
|
+
suppressedCount: 0
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
return results;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Main scan function
|
|
382
|
+
*/
|
|
383
|
+
async function scan(paths, options) {
|
|
384
|
+
// Validate paths exist
|
|
385
|
+
const scanRoot = paths[0] || '.';
|
|
386
|
+
if (!fs.existsSync(scanRoot)) {
|
|
387
|
+
console.error(`❌ Path not found: ${scanRoot}`);
|
|
388
|
+
return 3;
|
|
389
|
+
}
|
|
390
|
+
// Load .haloignore from the first scan path
|
|
391
|
+
let ignoreConfig;
|
|
392
|
+
try {
|
|
393
|
+
ignoreConfig = loadHaloignore(fs.statSync(scanRoot).isDirectory() ? scanRoot : path.dirname(scanRoot));
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
// Ignore errors loading .haloignore
|
|
397
|
+
}
|
|
398
|
+
if (options.verbose && ignoreConfig) {
|
|
399
|
+
console.error('📋 Loaded .haloignore configuration');
|
|
400
|
+
}
|
|
401
|
+
// Auto-detect project domains from package.json to reduce ext-017 FPs
|
|
402
|
+
const projectDomains = [];
|
|
403
|
+
try {
|
|
404
|
+
const projectRoot = fs.statSync(scanRoot).isDirectory() ? scanRoot : path.dirname(scanRoot);
|
|
405
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
406
|
+
if (fs.existsSync(pkgPath)) {
|
|
407
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
408
|
+
// Hosting platforms that should never be treated as "own domain"
|
|
409
|
+
const hostingPlatforms = ['github.com', 'github.io', 'gitlab.com', 'bitbucket.org', 'npmjs.com', 'npmjs.org', 'herokuapp.com', 'vercel.app', 'netlify.app'];
|
|
410
|
+
// Extract domains from homepage, repository, and name
|
|
411
|
+
if (pkg.homepage) {
|
|
412
|
+
try {
|
|
413
|
+
const url = new URL(pkg.homepage);
|
|
414
|
+
if (!hostingPlatforms.includes(url.hostname)) {
|
|
415
|
+
projectDomains.push(url.hostname);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
catch { /* not a URL */ }
|
|
419
|
+
}
|
|
420
|
+
if (typeof pkg.repository === 'string' && pkg.repository.includes('github.com')) {
|
|
421
|
+
// Extract org/repo name as potential domain hint
|
|
422
|
+
const repoMatch = pkg.repository.match(/github\.com[/:]([\w-]+)\/([\w-]+)/);
|
|
423
|
+
if (repoMatch) {
|
|
424
|
+
projectDomains.push(`${repoMatch[2]}.com`);
|
|
425
|
+
projectDomains.push(`${repoMatch[2]}.org`);
|
|
426
|
+
projectDomains.push(`${repoMatch[2]}.io`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
else if (pkg.repository?.url) {
|
|
430
|
+
const repoMatch = pkg.repository.url.match(/github\.com[/:]([\w-]+)\/([\w-]+)/);
|
|
431
|
+
if (repoMatch) {
|
|
432
|
+
projectDomains.push(`${repoMatch[2]}.com`);
|
|
433
|
+
projectDomains.push(`${repoMatch[2]}.org`);
|
|
434
|
+
projectDomains.push(`${repoMatch[2]}.io`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Use package name as domain hint
|
|
438
|
+
if (pkg.name) {
|
|
439
|
+
const cleanName = pkg.name.replace(/^@[\w-]+\//, '').replace(/-/g, '');
|
|
440
|
+
if (cleanName.length >= 3) {
|
|
441
|
+
projectDomains.push(`${cleanName}.com`);
|
|
442
|
+
projectDomains.push(`${cleanName}.org`);
|
|
443
|
+
projectDomains.push(`${cleanName}.io`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
// Ignore errors detecting project domains
|
|
450
|
+
}
|
|
451
|
+
if (options.verbose && projectDomains.length > 0) {
|
|
452
|
+
console.error(`🏠 Detected project domains: ${[...new Set(projectDomains)].join(', ')}`);
|
|
453
|
+
}
|
|
454
|
+
const engine = new engine_1.HaloEngine({
|
|
455
|
+
includePatterns: options.include,
|
|
456
|
+
excludePatterns: options.exclude,
|
|
457
|
+
rules: options.rules.length > 0 ? options.rules : undefined,
|
|
458
|
+
severityFilter: options.severity.length > 0 ? options.severity : undefined,
|
|
459
|
+
ignoreConfig,
|
|
460
|
+
projectDomains: projectDomains.length > 0 ? [...new Set(projectDomains)] : undefined,
|
|
461
|
+
ethical: options.ethicalPreview
|
|
462
|
+
});
|
|
463
|
+
const results = [];
|
|
464
|
+
let fileCount = 0;
|
|
465
|
+
// Collect all files to scan
|
|
466
|
+
const allFiles = [];
|
|
467
|
+
for (const scanPath of paths) {
|
|
468
|
+
const stats = fs.statSync(scanPath);
|
|
469
|
+
if (stats.isDirectory()) {
|
|
470
|
+
const patterns = options.include.length > 0
|
|
471
|
+
? options.include
|
|
472
|
+
: getDefaultPatterns();
|
|
473
|
+
const excludes = options.exclude.length > 0
|
|
474
|
+
? options.exclude
|
|
475
|
+
: getDefaultExcludePatterns();
|
|
476
|
+
for (const pattern of patterns) {
|
|
477
|
+
const fullPattern = path.join(scanPath, pattern);
|
|
478
|
+
const files = await (0, glob_1.glob)(fullPattern, {
|
|
479
|
+
ignore: excludes,
|
|
480
|
+
absolute: true
|
|
481
|
+
});
|
|
482
|
+
allFiles.push(...files);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
else if (stats.isFile()) {
|
|
486
|
+
allFiles.push(scanPath);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
// Deduplicate files
|
|
490
|
+
let uniqueFiles = [...new Set(allFiles)];
|
|
491
|
+
// Belt-and-suspenders: filter out test files that slip through glob exclusion
|
|
492
|
+
// (e.g., Django's tests.py files which aren't *inside* a tests/ directory)
|
|
493
|
+
const isTestFile = (filePath) => {
|
|
494
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
495
|
+
const segments = normalized.split('/');
|
|
496
|
+
// Check directory segments
|
|
497
|
+
if (segments.some(s => s === 'test' || s === 'tests' || s === '__tests__' ||
|
|
498
|
+
s === '__mocks__' || s === 'spec' || s === 'fixtures' ||
|
|
499
|
+
s === 'testing' || s === 'testdata'))
|
|
500
|
+
return true;
|
|
501
|
+
// Check file name patterns
|
|
502
|
+
const fileName = segments[segments.length - 1] || '';
|
|
503
|
+
if (/\.(?:test|spec)\.[jt]sx?$/.test(fileName))
|
|
504
|
+
return true;
|
|
505
|
+
if (/^test_.*\.py$/.test(fileName))
|
|
506
|
+
return true;
|
|
507
|
+
if (/^tests\.py$/.test(fileName))
|
|
508
|
+
return true;
|
|
509
|
+
if (/^conftest\.py$/.test(fileName))
|
|
510
|
+
return true;
|
|
511
|
+
if (/_test\.py$/.test(fileName))
|
|
512
|
+
return true;
|
|
513
|
+
if (/_test\.go$/.test(fileName))
|
|
514
|
+
return true;
|
|
515
|
+
return false;
|
|
516
|
+
};
|
|
517
|
+
const beforeFilter = uniqueFiles.length;
|
|
518
|
+
uniqueFiles = uniqueFiles.filter(f => !isTestFile(f));
|
|
519
|
+
const filteredCount = beforeFilter - uniqueFiles.length;
|
|
520
|
+
if (options.verbose) {
|
|
521
|
+
if (filteredCount > 0) {
|
|
522
|
+
console.error(`🧪 Excluded ${filteredCount} test files`);
|
|
523
|
+
}
|
|
524
|
+
console.error(`🔍 Scanning ${uniqueFiles.length} files...`);
|
|
525
|
+
}
|
|
526
|
+
// Max file size: 1MB (skip large/binary files)
|
|
527
|
+
const MAX_FILE_SIZE = 1024 * 1024;
|
|
528
|
+
// Scan each file
|
|
529
|
+
for (const filePath of uniqueFiles) {
|
|
530
|
+
try {
|
|
531
|
+
// Skip files that are too large (likely not source code)
|
|
532
|
+
const stat = fs.statSync(filePath);
|
|
533
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
534
|
+
if (options.verbose) {
|
|
535
|
+
console.error(`⏭️ Skipping large file: ${filePath} (${(stat.size / 1024).toFixed(0)}KB)`);
|
|
536
|
+
}
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
540
|
+
// Skip binary files (check for null bytes in first 512 chars)
|
|
541
|
+
if (content.substring(0, 512).includes('\0')) {
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const violations = engine.scanFile(filePath, content);
|
|
545
|
+
if (violations.length > 0) {
|
|
546
|
+
results.push({
|
|
547
|
+
filePath,
|
|
548
|
+
violations,
|
|
549
|
+
scannedAt: new Date().toISOString(),
|
|
550
|
+
totalViolations: violations.length,
|
|
551
|
+
suppressedCount: 0
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
fileCount++;
|
|
555
|
+
}
|
|
556
|
+
catch (err) {
|
|
557
|
+
if (options.verbose) {
|
|
558
|
+
console.error(`⚠️ Error reading ${filePath}:`, err);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
// Format output
|
|
563
|
+
let output;
|
|
564
|
+
switch (options.format) {
|
|
565
|
+
case 'sarif':
|
|
566
|
+
output = formatSARIF(results, engine.getRules());
|
|
567
|
+
break;
|
|
568
|
+
case 'json':
|
|
569
|
+
output = formatJSON(results);
|
|
570
|
+
break;
|
|
571
|
+
default:
|
|
572
|
+
output = formatText(results, options.verbose, fileCount);
|
|
573
|
+
}
|
|
574
|
+
// Write output (only one path — no duplication)
|
|
575
|
+
if (options.output) {
|
|
576
|
+
fs.writeFileSync(options.output, output);
|
|
577
|
+
console.error(`📄 Results written to ${options.output}`);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
process.stdout.write(output);
|
|
581
|
+
}
|
|
582
|
+
// Return exit code based on violations
|
|
583
|
+
const hasCriticalOrHigh = results.some(r => r.violations.some(v => v.severity === 'critical' || v.severity === 'high'));
|
|
584
|
+
if (hasCriticalOrHigh) {
|
|
585
|
+
return 2; // Critical violations found
|
|
586
|
+
}
|
|
587
|
+
if (results.length > 0) {
|
|
588
|
+
return 1; // Violations found (medium/low only)
|
|
589
|
+
}
|
|
590
|
+
return 0; // No violations
|
|
591
|
+
}
|
|
592
|
+
// CLI setup
|
|
593
|
+
program
|
|
594
|
+
.name('runhalo')
|
|
595
|
+
.description('Halo - Child Safety Compliance Scanner for COPPA 2.0')
|
|
596
|
+
.version('1.0.0');
|
|
597
|
+
program
|
|
598
|
+
.command('scan')
|
|
599
|
+
.description('Scan files or directories for COPPA violations')
|
|
600
|
+
.argument('[paths...]', 'Paths to scan (default: current directory)', ['.'])
|
|
601
|
+
.option('-f, --format <format>', 'Output format: json, sarif, text', 'text')
|
|
602
|
+
.option('-i, --include <patterns...>', 'File patterns to include')
|
|
603
|
+
.option('-e, --exclude <patterns...>', 'File patterns to exclude')
|
|
604
|
+
.option('-r, --rules <ruleIds...>', 'Specific rules to run (e.g., coppa-auth-001)')
|
|
605
|
+
.option('-s, --severity <levels...>', 'Filter by severity: critical, high, medium, low')
|
|
606
|
+
.option('-o, --output <file>', 'Output file path')
|
|
607
|
+
.option('--ethical-preview', 'Enable experimental ethical design rules (Sprint 5 preview)')
|
|
608
|
+
.option('-v, --verbose', 'Verbose output')
|
|
609
|
+
.action(async (paths, options) => {
|
|
610
|
+
try {
|
|
611
|
+
const exitCode = await scan(paths, {
|
|
612
|
+
format: options.format || 'text',
|
|
613
|
+
include: options.include || [],
|
|
614
|
+
exclude: options.exclude || [],
|
|
615
|
+
rules: options.rules || [],
|
|
616
|
+
severity: options.severity || [],
|
|
617
|
+
output: options.output || '',
|
|
618
|
+
verbose: options.verbose || false,
|
|
619
|
+
ethicalPreview: options.ethicalPreview || false
|
|
620
|
+
});
|
|
621
|
+
process.exit(exitCode);
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
console.error('❌ Error:', error instanceof Error ? error.message : error);
|
|
625
|
+
process.exit(3); // Fatal error
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
// Run CLI
|
|
629
|
+
if (require.main === module) {
|
|
630
|
+
program.parse();
|
|
631
|
+
}
|
|
632
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runhalo/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Halo CLI — scan your codebase for COPPA 2.0 privacy risks",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"runhalo": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/index.js",
|
|
12
|
+
"dist/index.js.map",
|
|
13
|
+
"dist/index.d.ts"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"prebuild": "cd ../engine && npm run build",
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"test": "jest --config jest.config.cjs",
|
|
19
|
+
"scan": "node dist/index.js scan"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"coppa",
|
|
23
|
+
"privacy",
|
|
24
|
+
"child-safety",
|
|
25
|
+
"cli",
|
|
26
|
+
"scanner",
|
|
27
|
+
"linter"
|
|
28
|
+
],
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/runhalo/halo.git",
|
|
32
|
+
"directory": "packages/cli"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://runhalo.dev",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/runhalo/halo/issues"
|
|
37
|
+
},
|
|
38
|
+
"author": "Mindful Media <hello@mindfulmedia.org> (https://mindfulmedia.org)",
|
|
39
|
+
"license": "Apache-2.0",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@runhalo/engine": "^0.1.0",
|
|
42
|
+
"commander": "^11.1.0",
|
|
43
|
+
"glob": "^10.3.10"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/jest": "^29.5.14",
|
|
47
|
+
"@types/node": "^20.10.0",
|
|
48
|
+
"jest": "^29.7.0",
|
|
49
|
+
"ts-jest": "^29.4.6",
|
|
50
|
+
"typescript": "^5.3.3"
|
|
51
|
+
}
|
|
52
|
+
}
|