#!/usr/bin/env node /** * Confidential Document Scanner - Enforces inst_012, inst_015 * Prevents deployment of internal/confidential documents */ const fs = require('fs'); const path = require('path'); // File patterns that indicate confidential/internal documents const CONFIDENTIAL_PATTERNS = [ /session[-_]?handoff/i, /phase[-_]?planning/i, /cost[-_]?estimate/i, /infrastructure[-_]?plan/i, /progress[-_]?report/i, /cover[-_]?letter/i, /testing[-_]?checklist/i, /internal/i, /confidential/i, /private/i, /draft/i, /wip[-_]/i, // work in progress /todo/i ]; // Content markers that indicate confidential information const CONFIDENTIAL_CONTENT_MARKERS = [ /\[INTERNAL\]/i, /\[CONFIDENTIAL\]/i, /\[DRAFT\]/i, /\[DO NOT PUBLISH\]/i, /\[WIP\]/i, /CONFIDENTIAL:/i, /INTERNAL ONLY:/i ]; function checkFilePath(filePath) { const basename = path.basename(filePath); for (const pattern of CONFIDENTIAL_PATTERNS) { if (pattern.test(basename) || pattern.test(filePath)) { return { confidential: true, reason: `Filename matches confidential pattern: ${pattern.source}` }; } } return { confidential: false }; } function checkFileContent(filePath) { try { const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split('\n'); for (let i = 0; i < Math.min(20, lines.length); i++) { for (const marker of CONFIDENTIAL_CONTENT_MARKERS) { if (marker.test(lines[i])) { return { confidential: true, reason: `Content contains confidential marker at line ${i+1}: ${marker.source}`, line: i + 1, text: lines[i].trim() }; } } } return { confidential: false }; } catch (err) { // Can't read file (binary, etc.) - check by path only return { confidential: false }; } } function scanFile(filePath) { // Skip non-document files const ext = path.extname(filePath).toLowerCase(); if (!['.md', '.txt', '.pdf', '.doc', '.docx', '.html'].includes(ext)) { return null; } // Check filename const pathCheck = checkFilePath(filePath); if (pathCheck.confidential) { return { file: filePath, ...pathCheck }; } // Check content const contentCheck = checkFileContent(filePath); if (contentCheck.confidential) { return { file: filePath, ...contentCheck }; } return null; } function main() { const args = process.argv.slice(2); if (args.length === 0) { console.log('Usage: check-confidential-docs.js [file2] ...'); console.log(''); console.log('Scans files to prevent deployment of internal/confidential documents'); process.exit(0); } console.log(`\nšŸ” Scanning ${args.length} file(s) for confidential markers...\n`); const findings = []; args.forEach(file => { if (!fs.existsSync(file)) return; const result = scanFile(file); if (result) { findings.push(result); } }); if (findings.length === 0) { console.log('āœ… No confidential documents detected\n'); process.exit(0); } // Report findings console.log(`āŒ Found ${findings.length} confidential document(s):\n`); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); findings.forEach(f => { console.log(`šŸ”“ ${f.file}`); console.log(` Reason: ${f.reason}`); if (f.text) { console.log(` Line ${f.line}: ${f.text.substring(0, 60)}...`); } console.log(''); }); console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'); console.log('āš ļø DEPLOYMENT BLOCKED (inst_012/inst_015)\n'); console.log('These documents are marked confidential/internal.'); console.log(''); console.log('Actions:'); console.log(' 1. Remove confidential markers if approved for public release'); console.log(' 2. Move to a non-public directory'); console.log(' 3. Get explicit human approval before deploying\n'); process.exit(1); } main();