@lanonasis/cli
Version:
Professional CLI for LanOnasis Memory as a Service (MaaS) with MCP support, seamless inline editing, and enterprise-grade security
89 lines (88 loc) • 4.14 kB
JavaScript
import { Command } from "commander";
import { PrivacySDK } from "@lanonasis/privacy-sdk";
import { prescan, saveReport, printSummary, getFlaggedFiles, getQuarantinedFiles, } from "@lanonasis/secret-prescan";
export const prescanScanCommand = new Command("scan")
.description("Scan a directory for secrets/PII before MIRA context extraction")
.argument("<path>", "Root directory to scan")
.option("-o, --output <dir>", "Output directory for JSON report (default: ~/.hermes/private/context-scans/)")
.option("-e, --exclude <patterns...>", "Glob patterns to exclude from scanning")
.option("--extensions <extensions...>", "File extensions to scan (default: .ts,.tsx,.js,.jsx,.mjs,.json,.env,.md,.yml)")
.option("--max-file-size <bytes>", "Maximum file size to scan in bytes (default: 10485760 = 10MB)")
.option("--include-clean", "Include clean files in the JSON report")
.option("--quarantine-threshold <count>", "Minimum critical detections to classify a file as quarantined (default: 1)")
.action(async (path, options) => {
const fs = await import("fs");
if (!fs.existsSync(path)) {
console.error(`❌ Error: Path does not exist: ${path}`);
process.exit(1);
}
const stat = fs.statSync(path);
if (!stat.isDirectory()) {
console.error(`❌ Error: Path is not a directory: ${path}`);
process.exit(1);
}
const config = {
target_path: path,
output_dir: options.output,
exclude_patterns: options.exclude,
include_extensions: options.extensions,
max_file_size: options.maxFileSize ? parseInt(options.maxFileSize, 10) : undefined,
include_clean: options.includeClean ?? false,
quarantine_threshold: options.quarantineThreshold
? parseInt(options.quarantineThreshold, 10)
: 1,
};
if (config.max_file_size !== undefined && isNaN(config.max_file_size)) {
console.error(`❌ Error: --max-file-size must be a number`);
process.exit(1);
}
if (config.quarantine_threshold !== undefined && isNaN(config.quarantine_threshold)) {
console.error(`❌ Error: --quarantine-threshold must be a number`);
process.exit(1);
}
console.error(`🔍 Starting prescan...`);
console.error(` Target: ${path}`);
try {
const sdk = new PrivacySDK();
const report = prescan(sdk, config);
printSummary(report);
const reportPath = saveReport(report, config.output_dir);
const flaggedFiles = getFlaggedFiles(report);
const quarantinedFiles = getQuarantinedFiles(report);
console.log("");
console.log("---PRESCAN SUMMARY---");
console.log(`total_files:${report.total_files}`);
console.log(`safe:${report.summary.safe}`);
console.log(`flagged:${report.summary.flagged}`);
console.log(`quarantined:${report.summary.quarantined}`);
console.log(`errors:${report.summary.errors}`);
console.log(`total_detections:${report.summary.total_detections}`);
console.log(`report_path:${reportPath}`);
if (flaggedFiles.length > 0) {
console.log("");
console.log("---FLAGGED FILES---");
flaggedFiles.forEach((f) => console.log(`FLAGGED:${f}`));
}
if (quarantinedFiles.length > 0) {
console.log("");
console.log("---QUARANTINED FILES---");
quarantinedFiles.forEach((f) => console.log(`QUARANTINED:${f}`));
}
if (quarantinedFiles.length > 0) {
console.error(`\n🔴 Quarantined files found. MIRA extraction should NOT proceed.`);
process.exit(2);
}
else if (flaggedFiles.length > 0) {
console.error(`\n⚠️ Flagged files found. Review required before MIRA extraction.`);
process.exit(1);
}
else {
console.error(`\n✅ No issues found. Safe for MIRA extraction.`);
process.exit(0);
}
}
catch (error) {
console.error(`❌ Prescan failed: ${error.message}`);
process.exit(1);
}
});