@runhalo/cli 0.1.0 → 0.4.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/README.md +97 -0
- package/dist/index.d.ts +154 -4
- package/dist/index.js +1889 -12
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @runhalo/cli
|
|
2
|
+
|
|
3
|
+
**Halo CLI** — scan your codebase for COPPA 2.0 privacy risks.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@runhalo/cli)
|
|
6
|
+
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
7
|
+
|
|
8
|
+
## What it does
|
|
9
|
+
|
|
10
|
+
One command scans your entire codebase for potential COPPA 2.0 violations and ethical design issues in children's apps. Powered by tree-sitter AST analysis with **20 COPPA rules** and **5 ethical design rules**.
|
|
11
|
+
|
|
12
|
+
## Quickstart
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Scan current directory
|
|
16
|
+
npx @runhalo/cli scan .
|
|
17
|
+
|
|
18
|
+
# Scan a specific directory
|
|
19
|
+
npx @runhalo/cli scan ./src
|
|
20
|
+
|
|
21
|
+
# JSON output for CI pipelines
|
|
22
|
+
npx @runhalo/cli scan . --format json
|
|
23
|
+
|
|
24
|
+
# SARIF output for GitHub Security tab
|
|
25
|
+
npx @runhalo/cli scan . --format sarif --output results.sarif
|
|
26
|
+
|
|
27
|
+
# Filter by severity
|
|
28
|
+
npx @runhalo/cli scan . --severity critical,high
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Example Output
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Halo COPPA Risk Scanner v0.1.1
|
|
35
|
+
|
|
36
|
+
Scanning... 142 files analyzed
|
|
37
|
+
|
|
38
|
+
src/auth/social-login.ts:24
|
|
39
|
+
coppa-auth-001 Unverified social login detected CRITICAL
|
|
40
|
+
|
|
41
|
+
src/services/analytics.ts:89
|
|
42
|
+
coppa-tracking-003 Third-party ad tracker found HIGH
|
|
43
|
+
|
|
44
|
+
src/components/Chat.tsx:15
|
|
45
|
+
coppa-ext-011 Unmoderated third-party chat HIGH
|
|
46
|
+
|
|
47
|
+
3 potential issues found | 142 files scanned | 97 checks passing
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Output Formats
|
|
51
|
+
|
|
52
|
+
| Format | Flag | Use Case |
|
|
53
|
+
|:-------|:-----|:---------|
|
|
54
|
+
| Text | `--format text` (default) | Terminal output |
|
|
55
|
+
| JSON | `--format json` | CI pipelines, tooling |
|
|
56
|
+
| SARIF | `--format sarif` | GitHub Security tab |
|
|
57
|
+
|
|
58
|
+
## GitHub Action
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
name: Halo COPPA Audit
|
|
62
|
+
on:
|
|
63
|
+
pull_request:
|
|
64
|
+
paths: ['**.ts', '**.js', '**.tsx', '**.jsx', '**.py']
|
|
65
|
+
|
|
66
|
+
jobs:
|
|
67
|
+
scan:
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
- uses: actions/setup-node@v4
|
|
72
|
+
with:
|
|
73
|
+
node-version: '20'
|
|
74
|
+
- run: npx @runhalo/cli scan . --format sarif --output results.sarif
|
|
75
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
76
|
+
with:
|
|
77
|
+
sarif_file: results.sarif
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Suppression
|
|
81
|
+
|
|
82
|
+
Suppress individual findings with inline comments:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// halo-ignore coppa-auth-001
|
|
86
|
+
const auth = signInWithPopup(provider);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Or use a `.haloignore` file at your project root.
|
|
90
|
+
|
|
91
|
+
## Full Documentation
|
|
92
|
+
|
|
93
|
+
See the [Halo monorepo](https://github.com/runhalo/halo) for the complete rule reference, VS Code extension, MCP server, and more.
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
Apache 2.0 — [Mindful Media](https://mindfulmedia.org)
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Halo CLI - Child Safety Compliance Scanner
|
|
4
4
|
* Usage: runhalo scan <path> [options]
|
|
5
5
|
*/
|
|
6
|
-
import { HaloEngine, Violation, ScanResult, EngineConfig } from '@runhalo/engine';
|
|
6
|
+
import { HaloEngine, Violation, ScanResult, EngineConfig, JSONRule } from '@runhalo/engine';
|
|
7
7
|
type OutputFormat = 'json' | 'sarif' | 'text';
|
|
8
8
|
interface CLIOptions {
|
|
9
9
|
format: OutputFormat;
|
|
@@ -14,6 +14,11 @@ interface CLIOptions {
|
|
|
14
14
|
output: string;
|
|
15
15
|
verbose: boolean;
|
|
16
16
|
ethicalPreview: boolean;
|
|
17
|
+
report: string | boolean;
|
|
18
|
+
aiAudit: boolean;
|
|
19
|
+
sectorAuSbd: boolean;
|
|
20
|
+
pack: string[];
|
|
21
|
+
offline: boolean;
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
24
|
* Format violations as SARIF output
|
|
@@ -22,11 +27,30 @@ declare function formatSARIF(results: ScanResult[], rules: any[]): string;
|
|
|
22
27
|
/**
|
|
23
28
|
* Format violations as JSON output
|
|
24
29
|
*/
|
|
25
|
-
declare function formatJSON(results: ScanResult[]): string;
|
|
30
|
+
declare function formatJSON(results: ScanResult[], scoreResult?: any): string;
|
|
26
31
|
/**
|
|
27
32
|
* Format violations as human-readable text
|
|
28
33
|
*/
|
|
29
|
-
declare function formatText(results: ScanResult[], verbose?: boolean, fileCount?: number): string;
|
|
34
|
+
declare function formatText(results: ScanResult[], verbose?: boolean, fileCount?: number, scoreResult?: any): string;
|
|
35
|
+
/**
|
|
36
|
+
* Format trend line comparing current score to last scan for the same project.
|
|
37
|
+
* Returns empty string if no prior history exists.
|
|
38
|
+
*/
|
|
39
|
+
declare function formatTrend(currentScore: number, projectPath: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Generate a self-contained HTML compliance report.
|
|
42
|
+
* Light theme for email-ability. All CSS inline. No external dependencies.
|
|
43
|
+
*/
|
|
44
|
+
declare function generateHtmlReport(results: ScanResult[], scoreResult: any, fileCount: number, projectPath: string, history?: ScanHistoryEntry[]): string;
|
|
45
|
+
/**
|
|
46
|
+
* Escape HTML special characters
|
|
47
|
+
*/
|
|
48
|
+
declare function escapeHtml(text: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Generate a government-procurement-grade PDF compliance report.
|
|
51
|
+
* Uses PDFKit — pure JS, no browser dependencies, CI-safe.
|
|
52
|
+
*/
|
|
53
|
+
declare function generatePdfReport(results: ScanResult[], scoreResult: any, fileCount: number, projectPath: string, history?: ScanHistoryEntry[]): Promise<Buffer>;
|
|
30
54
|
/**
|
|
31
55
|
* Create a Halo engine instance
|
|
32
56
|
*/
|
|
@@ -39,8 +63,134 @@ declare function scanFile(filePath: string, content?: string): Violation[];
|
|
|
39
63
|
* Scan a directory
|
|
40
64
|
*/
|
|
41
65
|
declare function scanDirectory(dirPath: string, config?: EngineConfig): Promise<ScanResult[]>;
|
|
66
|
+
declare const HALO_CONFIG_DIR: string;
|
|
67
|
+
declare const HALO_CONFIG_PATH: string;
|
|
68
|
+
declare const HALO_HISTORY_PATH: string;
|
|
69
|
+
declare const MAX_HISTORY_ENTRIES = 100;
|
|
70
|
+
declare const RULES_CACHE_PATH: string;
|
|
71
|
+
interface RulesCache {
|
|
72
|
+
etag: string | null;
|
|
73
|
+
packs: string[];
|
|
74
|
+
rules: JSONRule[];
|
|
75
|
+
fetchedAt: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Fetch rules from the Supabase rules-fetch edge function.
|
|
79
|
+
* Returns raw JSON rules (not compiled) or null on failure.
|
|
80
|
+
*/
|
|
81
|
+
declare function fetchRulesFromAPI(packs: string[], verbose: boolean): Promise<{
|
|
82
|
+
rules: JSONRule[];
|
|
83
|
+
etag: string | null;
|
|
84
|
+
} | null>;
|
|
85
|
+
/**
|
|
86
|
+
* Read the local rules cache.
|
|
87
|
+
*/
|
|
88
|
+
declare function readRulesCache(): RulesCache | null;
|
|
89
|
+
/**
|
|
90
|
+
* Write rules to the local cache.
|
|
91
|
+
*/
|
|
92
|
+
declare function writeRulesCache(etag: string | null, packs: string[], rules: JSONRule[]): void;
|
|
93
|
+
/**
|
|
94
|
+
* Load bundled baseline rules from @runhalo/engine's rules.json.
|
|
95
|
+
*/
|
|
96
|
+
declare function loadBaselineRules(packs: string[]): JSONRule[] | null;
|
|
97
|
+
/**
|
|
98
|
+
* Map CLI options to pack IDs.
|
|
99
|
+
* --pack takes precedence. Legacy flags (--ethical-preview, --ai-audit, --sector-au-sbd) are mapped.
|
|
100
|
+
*/
|
|
101
|
+
declare function resolvePacks(options: CLIOptions): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Resolve rules with fallback chain:
|
|
104
|
+
* API (fresh) → 304 cache hit → local cache (stale OK) → bundled baseline → null
|
|
105
|
+
*/
|
|
106
|
+
declare function resolveRules(packs: string[], offline: boolean, verbose: boolean): Promise<JSONRule[] | null>;
|
|
107
|
+
interface HaloConfig {
|
|
108
|
+
email?: string;
|
|
109
|
+
prompted: boolean;
|
|
110
|
+
promptedAt: string;
|
|
111
|
+
consent: boolean;
|
|
112
|
+
license_key?: string;
|
|
113
|
+
tier?: 'free' | 'pro' | 'enterprise';
|
|
114
|
+
scans_today?: number;
|
|
115
|
+
scan_date?: string;
|
|
116
|
+
}
|
|
117
|
+
interface ScanHistoryEntry {
|
|
118
|
+
scannedAt: string;
|
|
119
|
+
score: number;
|
|
120
|
+
grade: string;
|
|
121
|
+
totalViolations: number;
|
|
122
|
+
bySeverity: {
|
|
123
|
+
critical: number;
|
|
124
|
+
high: number;
|
|
125
|
+
medium: number;
|
|
126
|
+
low: number;
|
|
127
|
+
};
|
|
128
|
+
filesScanned: number;
|
|
129
|
+
projectPath: string;
|
|
130
|
+
rulesTriggered: string[];
|
|
131
|
+
}
|
|
132
|
+
declare function loadConfig(): HaloConfig | null;
|
|
133
|
+
declare function saveConfig(config: HaloConfig): void;
|
|
134
|
+
declare function loadHistory(): ScanHistoryEntry[];
|
|
135
|
+
declare function saveHistory(entry: ScanHistoryEntry): void;
|
|
136
|
+
declare const FREE_SCAN_LIMIT = 5;
|
|
137
|
+
/**
|
|
138
|
+
* Validate a license key against Supabase validate-license edge function.
|
|
139
|
+
* Returns license info or null on failure.
|
|
140
|
+
*/
|
|
141
|
+
declare function validateLicenseKey(licenseKey: string): Promise<{
|
|
142
|
+
valid: boolean;
|
|
143
|
+
tier?: string;
|
|
144
|
+
email?: string;
|
|
145
|
+
status?: string;
|
|
146
|
+
expires_at?: string;
|
|
147
|
+
error?: string;
|
|
148
|
+
} | null>;
|
|
149
|
+
/**
|
|
150
|
+
* Activate a license key — validates via Supabase, stores in ~/.halo/config.json.
|
|
151
|
+
*/
|
|
152
|
+
declare function activateLicense(licenseKey: string): Promise<number>;
|
|
153
|
+
/**
|
|
154
|
+
* Check scan limit for free-tier users.
|
|
155
|
+
* Returns true if scan is allowed, false if blocked.
|
|
156
|
+
* CI environments always bypass limits.
|
|
157
|
+
*/
|
|
158
|
+
declare function checkScanLimit(): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Check if a Pro feature is available for the current user.
|
|
161
|
+
* Returns true if allowed, false with upsell message if blocked.
|
|
162
|
+
*/
|
|
163
|
+
declare function checkProFeature(featureName: string, flagName: string): boolean;
|
|
164
|
+
/**
|
|
165
|
+
* First-run email prompt — one-time, optional, non-blocking.
|
|
166
|
+
* Auto-skips when: config exists, --no-prompt, !isTTY, CI env.
|
|
167
|
+
*/
|
|
168
|
+
declare function firstRunPrompt(noPrompt: boolean): Promise<void>;
|
|
42
169
|
/**
|
|
43
170
|
* Main scan function
|
|
44
171
|
*/
|
|
45
172
|
declare function scan(paths: string[], options: CLIOptions): Promise<number>;
|
|
46
|
-
|
|
173
|
+
interface FixCLIOptions {
|
|
174
|
+
dryRun: boolean;
|
|
175
|
+
rules: string[];
|
|
176
|
+
verbose: boolean;
|
|
177
|
+
include: string[];
|
|
178
|
+
exclude: string[];
|
|
179
|
+
guided: boolean;
|
|
180
|
+
framework?: string;
|
|
181
|
+
scaffoldDir?: string;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Main fix function
|
|
185
|
+
* Flow: discover files → scan → filter auto-fixable → apply fixes → re-scan → write (or dry-run)
|
|
186
|
+
*/
|
|
187
|
+
declare function fix(paths: string[], options: FixCLIOptions): Promise<number>;
|
|
188
|
+
interface InitOptions {
|
|
189
|
+
ide: boolean;
|
|
190
|
+
force: boolean;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Init command — generate IDE rules files and project configuration.
|
|
194
|
+
*/
|
|
195
|
+
declare function init(projectPath: string, options: InitOptions): Promise<number>;
|
|
196
|
+
export { scan, fix, init, scanFile, scanDirectory, createEngine, formatSARIF, formatJSON, formatText, loadConfig, saveConfig, firstRunPrompt, loadHistory, saveHistory, formatTrend, generateHtmlReport, generatePdfReport, escapeHtml, validateLicenseKey, activateLicense, checkScanLimit, checkProFeature, resolvePacks, resolveRules, fetchRulesFromAPI, readRulesCache, writeRulesCache, loadBaselineRules, FREE_SCAN_LIMIT, HALO_CONFIG_DIR, HALO_CONFIG_PATH, HALO_HISTORY_PATH, MAX_HISTORY_ENTRIES, RULES_CACHE_PATH };
|