@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 ADDED
@@ -0,0 +1,97 @@
1
+ # @runhalo/cli
2
+
3
+ **Halo CLI** — scan your codebase for COPPA 2.0 privacy risks.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@runhalo/cli.svg)](https://www.npmjs.com/package/@runhalo/cli)
6
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](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
- export { scan, scanFile, scanDirectory, createEngine, formatSARIF, formatJSON, formatText };
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 };